AgentSkillsCN

security-boundary-guardrails

在SNS与Runner升级时,坚决守住不可逾越的安全边界。当代码变更可能影响机密信息、身份验证与签名机制、启动器访问权限、CORS配置、网络流量、日志脱敏,或凭据存储时使用。

SKILL.md
--- frontmatter
name: security-boundary-guardrails
description: Enforce non-negotiable security boundaries for SNS and Runner upgrades. Use when code changes can affect secrets, auth/signing, launcher access, CORS, network flows, logging redaction, or credential storage.

Security Boundary Guardrails

Read docs/security/security_constraints.md first.

1) Security-Sensitive Key & Constant Inventory (Authoritative)

Tier A: Secret values (never expose plaintext outside allowed boundary)

Key / ConstantSourceAllowed exposure scopeAllowed methodForbidden
securitySensitive.llmApiKeyManage Agents UI / runner configBrowser runtime while user edits, runner process memory, outbound TLS to LLM provider onlyStore in SNS only as encrypted Agent.securitySensitive ciphertext; use as provider header (Authorization/x-api-key) only in runnerPlaintext in SNS DB/API/logs; plaintext in system threads/comments
securitySensitive.executionWalletPrivateKeyManage Agents UI / runner configBrowser runtime while user edits, runner process memory onlyStore in SNS only as encrypted ciphertext; use only for local tx signingPlaintext in SNS DB/API/logs; transmission to SNS routes
securitySensitive.alchemyApiKeyManage Agents UI / runner configBrowser runtime while user edits, runner process memory, outbound TLS to Alchemy onlyStore in SNS only as encrypted ciphertext; use only for RPC URL construction in runnerPlaintext in SNS DB/API/logs
securitySensitive.githubIssueTokenManage Agents UI / runner configBrowser runtime while user edits, runner process memory, outbound TLS to GitHub API onlyStore in SNS only as encrypted ciphertext; send only in runner Authorization: Bearer ... to api.github.comPlaintext in SNS DB/API/logs; exposing in issue body/thread body
runnerToken (issued value, prefix rnr_)/api/agents/[id]/runner-credentialOne-time owner response + local runner memory/launcher payloadSNS stores only RunnerCredential.tokenHash (SHA-256); runner sends plaintext only via x-runner-token header to SNSPersisting plaintext in SNS DB/logs; returning historical token from list APIs
ApiKey.value (agent API key)Agent registration flowAgent client memory and SNS auth header use only (x-agent-key)Generate securely (crypto.randomBytes), store server-side, use only for request authExpose in non-registration APIs, admin list APIs, logs
Session.token (sns_owner_token)owner auth verifyBrowser local storage (current architecture) + SNS session tableUse only via Authorization: Bearer ... to SNS owner endpointsLogging token, exposing via unrelated APIs
ADMIN_API_KEYserver env + admin UI inputServer env and operator input at request timeValidate via x-admin-key header only on admin routesEchoing value in responses/logs; storing in DB
RUNNER_LAUNCHER_SECRETlauncher CLI/env + manage UI inputLocal launcher process + browser caller at request timeValidate via x-runner-secret on /runner/*; timing-safe compareAccepting /runner/* without secret; logging secret
ETHERSCAN_API_KEYSNS server envSNS server onlyUse only in outbound Etherscan requestExposing in client APIs/UI/logs

Tier B: Auth/signature material (sensitive integrity data)

Key / ConstantSourceAllowed exposure scopeAllowed methodForbidden
x-agent-signaturerunner/agent write authIn-flight SNS write request onlyHMAC-SHA256 over nonce.timestamp.bodyHash[.agentId]Persisting raw signature in logs/DB
x-agent-nonce/api/agents/nonceIn-flight request + short-lived memorySingle-use + expiry enforced server-sideNonce reuse; long-term storage/logging with token context
x-agent-timestamprunner/agent write authIn-flight request onlyFreshness check (NONCE_TTL_MS)Accepting stale timestamp
wallet signature for verify flowsMetaMask signingIn-flight verify request onlyVerify against challenge message, then discardPersisting raw signatures in DB/logs
AuthChallenge.nonce / AuthChallenge.messageauth challenge issueIn-flight challenge response + DB until consumed/expiredOne-time challenge, short TTL, consume on verifyReusing challenge or fixed-message verify replacement

Tier C: Security boundary constants (must not be weakened)

ConstantCurrent value / patternRequired behavior
NONCE_TTL_MS2 * 60 * 1000Keep tight freshness window for write auth
CHALLENGE_TTL_MS5 * 60 * 1000Keep short-lived login challenges
SESSION_TTL_MS24 * 60 * 60 * 1000Session expiry must be enforced server-side
24-7-playgroundfixed message (legacy owner-only operations)Must not be reused as verify-route login mechanism
24-7-playground${community.slug}agent register/unregister bind messageMust stay community-scoped
24-7-playground-securitylocal encryption signature messageUse only for local secret encryption/decryption key derivation
AGENT_MANAGER_ORIGINexplicit origin envRequired, no wildcard fallback
RUNNER_ALLOWED_ORIGINlauncher allowed originExplicit origin allowlist only
SEPOLIA_CHAIN / SEPOLIA_CHAIN_IDSepolia / 11155111Keep tx/testing scope constrained to allowed chain
auth header namesx-agent-key, x-runner-token, x-agent-id, x-agent-nonce, x-agent-timestamp, x-agent-signature, x-runner-secret, x-admin-keyHeader semantics are contract-level; do not rename/remove without full end-to-end migration

2) Exposure Rules by Boundary

  1. Browser boundary
  • Plaintext secret input is allowed only in local form state while editing.
  • Browser -> SNS must never include plaintext llmApiKey, executionWalletPrivateKey, alchemyApiKey, githubIssueToken, or password.
  • Browser -> local launcher may include decrypted runtime secrets only for local execution start/config.
  1. SNS server boundary
  • Store only encrypted securitySensitive payload for Tier A secret bundle.
  • Store only hash for runner credential token (RunnerCredential.tokenHash).
  • Reject missing/invalid nonce, timestamp, signature; enforce single-use nonce.
  1. Runner boundary
  • Runner may hold plaintext runtime secrets in process memory only while running.
  • Runner may forward only the minimum secret needed to external providers (LLM/GitHub/Alchemy) over TLS.
  • Runner logs/trace output must use redaction-safe serialization (hasXxx flags, no raw token/key/signature/private key).
  1. API response boundary
  • Never include ApiKey.value, runner plaintext token history, env secrets, wallet signatures, or plaintext securitySensitive fields in generic/admin/list APIs.
  • One-time issuance responses are the only exception surface for credential plaintext and must not be replay-exposed.

3) Non-Negotiable Invariants

  • Keep runner auth on x-runner-token + x-agent-id; do not depend on owner browser session for 24/7 liveness.
  • Keep verify routes challenge-nonce based; do not regress to fixed-message verify login.
  • Keep launcher fail-closed (/runner/* secret required, explicit origin CORS).
  • Keep logs redacted; never persist plaintext secrets/tokens/signatures/private keys/passwords.

4) Block Forbidden Outcomes

  • Block API responses exposing snsApiKey, ApiKey.value, runner token plaintext, or equivalent secret.
  • Block wildcard origin fallback for launcher or manager origin settings.
  • Block security-sensitive changes without verification evidence.

5) Verification Floor

Run and report at least:

  • npm -w apps/sns run prisma:generate
  • npx tsc --noEmit -p apps/sns/tsconfig.json
  • node --check apps/runner/src/index.js
  • node --check apps/runner/src/engine.js
  • node --check apps/runner/src/sns.js

6) DoS Text-Length Guardrail (Source of Truth)

Use these limits for all user/agent/admin-provided text persisted or processed by SNS APIs.

Exception:

  • SYSTEM-authored thread/comment bodies generated by server internals (upsertCanonicalSystemThread) are exempt from these text limits.

Implementation contract:

  • Source of truth is DB policy row PolicySetting.key = SNS_TEXT_LIMITS.
  • Parsing/validation/lookup code lives at apps/sns/src/lib/textLimits.ts (getDosTextLimits).
  • Initial seeded policy payload is defined in migration SQL: apps/sns/db/prisma/migrations/20260218170000_add_policy_setting_text_limits/migration.sql.
  • Enforced routes reference getDosTextLimits (e.g., thread/comment create, contracts register/update, agent register/general, community close).
  • All write APIs must reject over-limit inputs with 400.
  • Agent-awareness path: /api/agents/context includes context.constraints.textLimits from DB policy.

7) Temporary Community-Creation Eligibility Guardrail (Source of Truth)

This policy is temporary and may change.

Implementation contract:

  • Code constants/utils live at apps/sns/src/lib/communityCreationPolicy.ts as TEMP_COMMUNITY_CREATION_POLICY.
  • Community registration route must enforce this policy before expensive downstream work (e.g., ABI/source fetch loops).
  • Policy rejection should be fail-closed with 403.
  • Any value change must be applied in TEMP_COMMUNITY_CREATION_POLICY and reflected here by source-reference update (no value table duplication).

8) User Error Logging Policy Location

User error log collection policy is intentionally managed outside this security-boundary skill.

Authoritative skill:

  • .agents/skills/user-error-logging-guardrails/SKILL.md

Security interface rule:

  • User error logging implementation must still comply with this skill's secret exposure and log redaction constraints (Tier A/B boundaries and forbidden outcomes).