KeiSeiKit-1.0/docs/SECURITY.md
Parfii-bot ce9ba61ee0 docs(readme): split 89 KB monolith into hero-pitch + 6 docs/ files
README down from 89 KB to 7.8 KB (11x reduction, target was 10-15 KB).
Visitor-facing README now loads in one screen — hero + 3 killer features
+ what-it-solves + quick install + docs index.

Extracted 6 new files under docs/:

- INSTALL.md (15 KB) — prerequisites, profiles, interactive install,
  MCP binary, keisei CLI intro, runtime hook controls, what-you-get table
- REFERENCE.md (35 KB) — every one of 25 Rust primitives + 13 shell
  primitives + 10 hooks + 39 skills with actual CLI surface (clap flags,
  exit codes, env vars, state paths), keisei CLI deep-dive, 12 pipelines
- ARCHITECTURE.md (11 KB) — build pipeline, creating-a-new-agent,
  adding custom blocks/manifests, agents overview, cross-tool bridges,
  meta-composer, regen counts, workflow-file editing protocol
- SLEEP-LAYER.md (11 KB) — three-phase nightly cycle diagram,
  session self-audit (RULE 0.14), Cloud REM sync, sleep-on-it incubation,
  deep-sleep NREM consolidation with 4-primitive pipeline + example
- SECURITY.md (7.6 KB) — threat surface table + 8 mitigations in detail
  (memory-repo privacy, secrets-guard patterns, supply-chain SHA pinning,
  S3 SSRF, brain path/name validation, exFAT warning, battle matrix)
- WHY.md (3.6 KB) — full 'From the author' manifesto restored from
  git history (pre-1f3aaca product pivot). Medium/dev.to-friendly for
  virality, separate from the product README

New docs cross-link each other + README has docs index in tail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 22:20:22 +08:00

7.4 KiB
Raw Blame History

Security model

What the kit touches, what it never touches, and the mitigations baked in.


Threat surface overview

Risk Where it lives Mitigation
Memory-repo leaks session content Sleep-sync pushes trace JSONL off-machine Private repo enforced by wizard; [PATENT-IP] sessions skip push entirely
Hardcoded tokens in source Edits by agents / humans secrets-guard Rust hook (PreToolUse Edit|Write) blocks known token shapes
GitHub push of patent-sensitive content git push command no-github-push.sh hook + genesis-leak-guard.sh pre-commit symlink
Malicious GitHub Action tag re-point .github/workflows/*.yml SHA-pinning + validate-workflow-shas.sh + actionlint in CI
S3 SSRF / IMDS credential exfil kei-store with custom endpoint validate_endpoint rejects loopback / link-local / metadata hosts
Escape-sequence injection via brain name keisei status / attach output Control-byte sanitiser on every manifest-sourced string
Brain → $HOME pivot via symlink keisei attach <USB> Brain root rejected if symlink; mcp_server path must be relative + inside brain
SQLite WAL corruption on USB mount keisei mount <exFAT drive> Runtime advisory; exFAT/FAT32 warning in USB guide

Key mitigations in detail

Memory-repo must be private

Sleep-sync pushes your session traces (prompts, tool calls, file paths, code snippets) to a git repo you control. /sleep-setup Phase 1 warns loudly on PUBLIC visibility. A public memory-repo leaks everything your agents have seen.

If the session is marked [PATENT-IP] in the prompt or runs in a banned-project CWD, session-end-dump.sh skips the push entirely — local trace is kept, never leaves the machine.

No GitHub push for kit-internal state

RULE 0.1 forbids git push to github.com for any repo containing unfiled-patent IP. Kit ships genesis-leak-guard.sh as a pre-commit hook symlink template to keep patent-sensitive terms off any remote.

Override for legitimate public push: set env GENESIS_LEAK_BYPASS=1 for the single commit + document the bypass reason in the commit body. The hook logs every bypass to ~/.claude/memory/genesis-bypass-log.md.

Secrets by reference only

secrets-guard Rust hook blocks hardcoded tokens at PreToolUse(Edit|Write). Every SSH key, API key, deploy token lives in ~/.claude/secrets/.env (chmod 600, gitignored) or per-project secrets/*.env.

Hook detects these token shapes:

Pattern Source
sk-[A-Za-z0-9]{20+} OpenAI/Anthropic legacy
sk-ant-[A-Za-z0-9_-]{40+} Anthropic current
ghp_[A-Za-z0-9]{36} GitHub classic PAT
github_pat_[A-Za-z0-9_]{82} GitHub fine-grained
xoxb-[0-9]+-[0-9]+-[A-Za-z0-9]+ Slack bot
[0-9]{8,10}:[A-Za-z0-9_-]{35} Telegram bot
AKIA[A-Z0-9]{16} AWS access key
-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY----- PEM private keys
Bearer [A-Za-z0-9._-]{20+} generic bearer

Allowlist (no false-positives): env references ($VAR, os.environ[...], std::env::var(...)), placeholders (YOUR_TOKEN_HERE, <redacted>), safe paths (*/secrets/**, *.env.example).

Bypass for emergency: set env SECRETS_GUARD_BYPASS=1 on the single call.

Supply-chain defences

All GitHub Actions in .github/workflows/ are pinned by full commit SHA (defends against CVE-2025-30066-class mutable-tag attacks).

  • scripts/validate-workflow-shas.sh verifies every pin exists upstream via git ls-remote
  • scripts/install-actionlint.sh checks SHA-256 of the downloaded tarball before extraction
  • scripts/lint-workflows.sh runs actionlint over every workflow file
  • CI job workflow-lint runs all three on every push + PR (< 30 s)
  • dependabot.yml raises weekly PRs for SHA updates across github-actions, npm, and cargo ecosystems

S3 / R2 / MinIO hardening

kei-store::s3_cloud::validate_endpoint rejects loopback, link-local, and cloud-metadata hosts by default to close the SSRF / IMDS-credential-leak surface:

  • 127.0.0.0/8, ::1 (loopback)
  • 169.254.0.0/16, fe80::/10 (link-local)
  • metadata.google.internal, metadata.aws.internal (cloud metadata)

Plain HTTP requires opt-in via KEI_STORE_S3_ALLOW_INSECURE=1. When a custom (non-AWS) endpoint is set, explicit access_key_env + secret_key_env are REQUIRED — the AWS default credential chain is not consulted for non-AWS endpoints (closes the "IMDS credentials leaked to unrelated endpoint" path).

Brain attach-marker is owner-only

~/.keisei/attached.toml is chmod 0o600 on unix (Windows unchanged — no equivalent bit). Every manifest-sourced string printed by keisei status / attach / mount / detach is scrubbed through display::sanitize_display, which replaces every ASCII control byte (< 0x20 or == 0x7F) with ?. Closes the escape-sequence-injection surface from a malicious brain.name like "evil\x1b[2Jpayload" that would otherwise clear the user's terminal or rewrite already-printed lines.

manifest.toml is capped at 64 KiB — fs::metadata check runs before read_to_string so an attacker-supplied 1 GB file can't exhaust memory inside the TOML parser.

Brain path & name validation

  • Brain mcp_server path MUST be relative + inside the brain root (rejects /usr/bin/curl, ../../etc/shadow, Windows-style ..\..\)
  • Brain name matches ^[a-z][a-z0-9_-]{0,63}$
  • Brain root rejected if it's a symlink (blocks USB → $HOME pivot)
  • Adapters refuse to clobber existing mcpServers.<name> entries — explicit NameConflict error, no silent overwrite
  • All config writes go through fsx::write_atomic_json (Windows-safe via tempfile::NamedTempFile::persist)

exFAT / FAT32 warning

SQLite WAL shared-memory mmap is unreliable on those filesystems; keisei mount (multi-client) WILL corrupt kei-memory / kei-artifact / kei-social-store DBs. Brain load prints an advisory when exFAT/FAT32 is detected via statfs(2). Single-client keisei attach on exFAT stays supported.

See USB-BRAIN-GUIDE-macos.md / -linux.md / -windows.md for APFS / ext4 / NTFS-native walkthroughs.

Battle-test matrix

Install-test battle matrix runs every profile against three base images before each release (tests/battle/):

Image Libc Known quirks
ubuntu:24.04 glibc baseline; most widely deployed
alpine:3.19 musl exposes musl-static-link issues in rusqlite, git2, aws-sdk-s3
debian:12 bookworm glibc different apt structure from Ubuntu

Assertions per run: blocks ≥ 79, skills ≥ 39, top hooks ≥ 10, _lib hooks ≥ 2; hooks/_lib/test-gate.sh runs; settings.json validates. "Does it work on a fresh machine?" signal before every version ships.

See tests/battle/README.md for running locally.

Rule references

For the underlying discipline: these mitigations are driven by rules in the user's Claude Code CLAUDE.md. The relevant ones:

  • RULE 0.1 — NO GITHUB PUSH (unless patent-IP review clears)
  • RULE 0.4 — NO HALLUCINATION / CITATION VERIFY
  • RULE 0.8 — SECRETS SINGLE SOURCE
  • RULE 0.10 — RECURRENCE ESCALATE (same mistake ≥2× → codify via /escalate-recurrence)
  • RULE 0.13 — ORCHESTRATOR BRANCH FIRST (agents write files; orchestrator owns git)
  • RULE 0.14 — SESSION SELF-AUDIT
  • RULE 0.15 — SLEEP LAYER (three-phase nightly consolidation)