Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/use/first-steps.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ integration, value, or secret reference, then run work through **execute**.
in `execute`, then build the downstream artifact.
- **Ask for natural-language goals**, for example: “Search Kody for GitHub pull
request automation” or “Find a saved package for Cloudflare DNS helpers.”
- **Do not paste secrets in chat.** Use saved secrets, generated UI, or the
flows described in
- **Credentials use connect flows.** Use saved secrets, `/connect/oauth`,
`/connect/secret`, or the flows described in
[Secrets, values, and host approval](./secrets-and-values.md).
- **Confirm destructive work** before mutating GitHub, Cloudflare, or Cursor
Cloud Agents. See [Mutating actions and confirmations](./mutating-actions.md).
Expand Down
6 changes: 3 additions & 3 deletions docs/use/secrets-and-values.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

## Secrets

Secret **values** do not belong in chat. Prefer **saved secrets**, **generated
UI** flows, or execution-time persistence when a token already exists inside
trusted code.
Credential setup uses **saved secrets**, **`/connect/oauth`** for OAuth,
**`/connect/secret`** for API keys and PATs, or execution-time persistence when
a token already exists inside trusted code.

Use **search** first to discover saved secret references or integrations before
switching to **execute**.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const secretDeleteCapability = defineDomainCapability(
{
name: 'secret_delete',
description:
'Delete an existing secret reference for the signed-in user without revealing its plaintext value. Never ask the user to paste a secret, token, API key, password, or credential into chat; use generated UI to collect missing user-provided secrets safely. Use this when a secret should no longer be available to execute-time code.',
'Delete an existing secret reference for the signed-in user. Plaintext values stay hidden. Use `/connect/secret` for user-provided API key, token, and credential entry or rotation. Use this to remove execute-time access to a secret.',
keywords: ['secret', 'delete', 'remove', 'revoke', 'credential'],
readOnly: false,
idempotent: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const secretListCapability = defineDomainCapability(
{
name: 'secret_list',
description:
'List available secret references for the signed-in user without revealing secret values. When scope is omitted, results include every accessible scope in precedence order. Use `codemode.secret_list({ scope })` inside execute-time code when you want the same metadata, including allowed hosts and allowed capabilities, from the sandbox. Never return a secret value from execute, and never ask the user to paste a secret, token, API key, password, or credential into chat; use generated UI to collect missing secrets safely.',
'List available secret references for the signed-in user. Results include metadata such as names, descriptions, allowed hosts, and allowed capabilities. Use `codemode.secret_list({ scope })` inside execute-time code when you want the same metadata from the sandbox. Use `/connect/secret` for user-provided API key, token, and credential entry or rotation.',
keywords: ['secret', 'list', 'discovery', 'metadata', 'credentials'],
readOnly: true,
idempotent: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/worker/src/mcp/capabilities/secrets/secret-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const secretSetCapability = defineDomainCapability(
{
name: 'secret_set',
description:
'Create or update a stored secret reference for the signed-in user without ever returning the plaintext value. Use this only for server-side persistence of secret values that are already available inside trusted execution, such as refreshed OAuth tokens. Never ask the user to paste a secret, token, API key, password, or credential into chat; use generated UI to collect missing user-provided secrets safely. Saving a secret value does not authorize outbound host use or direct capability access.',
'Create or update a stored secret reference for the signed-in user. Use this for server-side persistence of secret values that are already available inside trusted execution, such as refreshed OAuth tokens. Use `/connect/secret` for user-provided API key, token, and credential entry or rotation. Host use and direct capability access are authorized through secret policy approvals.',
keywords: ['secret', 'persist', 'store', 'oauth', 'token', 'credential'],
readOnly: false,
idempotent: false,
Expand Down
7 changes: 3 additions & 4 deletions packages/worker/src/mcp/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export type ExecutionErrorDetails =
nextStep: string
secretNames: Array<string>
suggestedAction: {
type: 'open_generated_ui'
type: 'connect_secret'
reason: 'collect_secret'
}
}
Expand Down Expand Up @@ -248,11 +248,10 @@ export function getExecutionErrorDetails(
return {
kind: 'secret_required',
message,
nextStep:
'Open a generated UI so the user can provide and save this secret, then retry the workflow. Do not ask the user to paste the secret into chat.',
nextStep: `Send the user to /connect/secret?name=${encodeURIComponent(missingSecretDetails.secretName)} so they can provide and save this secret, then retry the workflow.`,
secretNames: [missingSecretDetails.secretName],
suggestedAction: {
type: 'open_generated_ui',
type: 'connect_secret',
reason: 'collect_secret',
},
}
Expand Down
6 changes: 3 additions & 3 deletions packages/worker/src/mcp/server-instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ https://github.com/kentcdodds/kody/tree/main/docs/use
Three-step flow:
1. \`search\` — built-in capabilities, saved packages, persisted values, saved integrations, and secret references (metadata).
2. \`execute\` — run one ephemeral module with imports/exports and runtime access through \`kody:runtime\`.
3. \`open_generated_ui\` — open UI when a package or inline UI flow needs user interaction.
3. \`open_generated_ui\` — open saved package apps or inline MCP App workflows.

Conventions
- ${conversationIdGuidance}
- \`memoryContext\`: short and task-focused. Kody may use it to surface a few relevant long-term memories and suppress repeats within the same \`conversationId\`.
- Do not ask the user to paste secrets in chat; use saved secrets or \`open_generated_ui\`.
- Credential setup uses the standard connect pages: \`/connect/oauth\` for OAuth integrations and reconnects, \`/connect/secret\` for API keys, PATs, and other user-provided secrets.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security prohibition against pasting secrets in chat removed

High Severity

Every explicit "never ask the user to paste a secret/token/credential into chat" prohibition has been removed from the always-present MCP system instructions (server-instructions.ts), tool descriptions (execute.ts, open-generated-ui.ts), and capability descriptions (secret-list.ts, secret-set.ts, secret-delete.ts). The replacement text tells the AI what to use (/connect/secret, /connect/oauth) but no longer tells it what not to do. The only remaining prohibition lives in docs/guides/connect-secret.md, which is loaded on-demand. Positive instructions alone don't prevent the AI from also offering to accept secrets in chat as a fallback.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 639a10b. Configure here.

- \`package_save\`: create or replace a repo-backed saved package rooted at \`package.json\`. Standard package exports define the package surface. \`package.json#kody\` contains Kody-specific metadata such as tags, optional app config, and package-owned jobs. When creating or materially changing a package, keep a root \`README.md\` \`## Intent\` section with the user's goal; ask the user if unclear and update it when scope expands.
- \`package_get\` / \`package_list\` / \`package_delete\`: inspect or manage saved packages for the signed-in user.
- Integration-backed work: use \`search\` and official guides before local repo exploration. For packages, package apps, or workflows that depend on third-party auth, first call \`kody_official_guide\` with \`guide: "integration_bootstrap"\`, confirm the required \`integration\` or \`secret\` entity exists through \`search\`, run a cheap authenticated \`execute\` smoke test, then build. If setup is missing, load \`oauth\` for \`/connect/oauth\`, \`connect_secret\` for secret collection, and \`secret_backed_integration\` for the default non-OAuth recipe.
Expand Down Expand Up @@ -97,7 +97,7 @@ execute
- Do not save or present an auth-dependent package as complete until \`search\` shows the required integration or secret reference exists and a minimal authenticated \`execute\` smoke test succeeds.

open_generated_ui
- Use UI when the package needs user interaction or sensitive input. Details: \`open_generated_ui\` tool description.
- Opens saved package apps and inline MCP App workflows. Details: \`open_generated_ui\` tool description.
`.trim()
}

Expand Down
2 changes: 1 addition & 1 deletion packages/worker/src/mcp/tools/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Sandbox surface:
- No \`secret_get\` / \`secrets\` helpers in the sandbox.
- \`value_get\` / \`value_list\` for non-secret persisted config.

Never ask the user to paste credentials in chat; use generated UI to collect or rotate secrets. If a host is not approved, use the error’s approval path instead of blind retries.
Credential collection and rotation use standard Kody connect pages: \`/connect/oauth\` for OAuth integrations and \`/connect/secret\` for API keys, PATs, and other user-provided secrets. For host approval failures, use the error’s approval path.

Prefer one \`execute\` when the workflow is clear; split calls when you need new user input or a changed plan.

Expand Down
3 changes: 2 additions & 1 deletion packages/worker/src/mcp/tools/open-generated-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ const openGeneratedUiTool = {
Open the MCP App runtime. Pass exactly one of \`code\` (inline HTML fragment or
full document) or \`kody_id\` (saved package app identity).

Use for sensitive input (never ask the user to paste credentials in chat).
Use when a saved package app or inline MCP App workflow should be shown inside
the host.
Recoverable errors: show in the UI and \`sendMessage(...)\` with the next step.
If the package app depends on a third-party integration, load
\`kody_official_guide\` (\`guide: "integration_bootstrap"\`) before building or
Expand Down
5 changes: 3 additions & 2 deletions packages/worker/src/mcp/tools/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1432,8 +1432,9 @@ Packages: \`package_list\`, \`package_get\`, and \`repo_*\` for editing/publishi
For package creation or material updates, load \`kody_official_guide\` with
\`guide: "package_authoring"\` and maintain a root README.md Intent section.
Open package apps with \`open_generated_ui({ kody_id })\` or use hosted package URLs.
Secrets: never raw in results; use
\`codemode.secret_list\` during execute and UI for missing values.
Secrets: results expose metadata; use \`codemode.secret_list\` during execute,
\`/connect/secret\` for API key/PAT entry and rotation, and \`/connect/oauth\`
for OAuth integrations.
Persisted values use \`codemode.value_get\` / \`codemode.value_list\`. Integrations
use \`codemode.integration_get\` / \`codemode.integration_list\`.

Expand Down
Loading