Poke Hardening Guide
Harden Poke messaging identity, connected accounts, action-capable API ingress, shared recipes, custom MCP and attended local tunnels.
Overview
This is a product guide within the Cognition platform. Harden Poke messaging identity, connected accounts, action-capable API ingress, shared recipes, custom MCP and attended local tunnels.
Intended Audience
- Account and endpoint administrators
- Integration/developer-platform owners
- Security and GRC teams reviewing effective access and evidence
How to Use This Guide
- L1 (Crawl): Establish identity ownership and protect sensitive state.
- L2 (Walk): Restrict effective integration and execution authority.
- Pilot changes in a disposable environment with recovery and approved rollback. Configuration evidence and denial tests are separate from policy intent.
Scope
Poke is the personal assistant continued under Cognition after the July 23 Interaction team announcement. Its phone/messaging identity, contract, Kitchen keys and integrations are separate from Devin Cloud SSO/SCIM. No enterprise SSO/RBAC/MDM capability is inferred from common ownership. Human assistance is task-scoped in the FAQ; that does not establish an organization-wide access policy or audit exporter.
Validation status: no tenants declared — Tier 0+1 only. This guide was researched from public configuration documentation and tested with local fixtures/stubs. No login, key creation, enrollment, integration, live product call or policy change was performed. It remains ai-drafted.
Table of Contents
1. Identity & Connected Accounts
1.1 Minimize Connected Account Authority
Profile Level: L1 (Crawl)
Description
Connect only the mail, calendar, files and other accounts needed for the task. Poke is a personal assistant with its own connected-account identity, not an organization configured by Devin SSO.
Rationale
Why This Matters:
- Connected mail/calendar integrations can perform actions, not only read notifications.
- Disconnecting one integration does not remove other accounts, existing exports or scheduled work.
Attack Prevented: Overbroad connected-account access and continued automation after offboarding.
Prerequisites
Owner of the Poke account and upstream account/provider consent.
ClickOps Implementation
- Open poke.com/integrations, select an integration and inspect the connected account and upstream permissions before accepting consent. Use a dedicated low-privilege account for shared or automated work.
- For unused access choose the connected account → Disconnect from Poke. If compromise is suspected, also revoke provider grants/sessions and inspect actions, recipes and other remaining integrations.
- Review Retry/Refresh reauthorization carefully; it can restore access previously interrupted by provider authentication. Maintain an owner and purpose for every connection.
Automation: The fetched integration guide documents account connection/disconnection in the UI. No administrative inventory/disconnect REST/GraphQL API, Terraform provider or distinct SDK was linked in the fetched Poke developer catalog; private/unlisted interfaces remain unverified. The message API is not an account-access setter.
Validation & Testing
Inspect the upstream account’s connected applications and effective permissions. On an authorized pilot disconnect one integration and confirm its tools stop while unrelated connections remain understood. No real connection or token was created for this guide.
Compliance Mappings
| Framework | Control | Mapping intent |
|---|---|---|
| SOC 2 | CC6.1, CC7.2 | Supports access and monitoring objectives |
| NIST SP 800-53 Rev. 5 | AC-2, AC-6, IA-5 | Supports configuration and access objectives |
| ISO 27001:2022 | A.5.15, A.8.9 | Supports access and configuration management |
Sources: Managing integrations, FAQ (retrieved 2026-11-05; no live validation).
1.2 Protect Messaging Identity and Account Lifecycle
Profile Level: L1 (Crawl)
Description
Review linked phone/messaging identities and account merge/deletion consequences before transferring or retiring an account.
Rationale
Why This Matters:
- A merge keeps the selected account’s memory, recipes and integrations; the other account’s data is scheduled for deletion.
- Account deletion can take up to 24 hours and retained backups/legal obligations have separate handling.
Attack Prevented: Wrong-account ownership, accidental disclosure through a transferred number and unintended retention.
Prerequisites
Control of the verified messaging channels, account owner and retention/legal-hold decision.
ClickOps Implementation
- In Settings → messaging review the preferred SMS, WhatsApp or Telegram channel. Follow the documented phone verification flow; never share verification codes.
- For a merge use Settings → phone number and the documented verification prompts. Review exactly which account is kept before confirming. Other messaging channels migrate; the discarded account’s data is deleted after 30 days, so retain approved records first.
- For retirement open Settings → Privacy → Delete Account. Disconnect sensitive upstream integrations and revoke keys/grants as part of containment; deletion timing does not prove every upstream token/session is gone.
Code Implementation
The first-party CLI wrapper runs whoami only through an already installed, trusted local Poke package, with npm offline/no-install settings. It creates a protected identity evidence file and does not log in, merge, delete or install anything. CLI logout and account deletion have different scopes.
Code Pack: CLI Script
set +x
set -Eeuo pipefail
umask 077
case "${HTH_PROFILE_LEVEL:-1}" in 1|2|3|4) ;; *) printf 'UNKNOWN: HTH_PROFILE_LEVEL must be 1..4.\n' >&2; exit 2 ;; esac
[[ $# == 0 && -d ${HTH_EVIDENCE_DIR:-} && ! -L ${HTH_EVIDENCE_DIR:-} ]] || { printf 'UNKNOWN: set a trusted existing HTH_EVIDENCE_DIR.\n' >&2; exit 2; }
command -v npx >/dev/null || { printf 'UNKNOWN: npx and an approved local poke package are required.\n' >&2; exit 2; }
out="$(mktemp -d "$HTH_EVIDENCE_DIR/poke-identity.XXXXXX")"
if ! npm_config_offline=true npm_config_yes=false npx --no-install poke whoami > "$out/identity.txt" 2> "$out/error.txt"; then
printf 'UNKNOWN: identity command failed; protected diagnostic file: %s/error.txt\n' "$out" >&2; exit 2
fi
printf 'COLLECTED identity only: %s/identity.txt (review privately; not an access-policy verdict).\n' "$out"
Validation & Testing
Review the private identity result against the intended account. Independently confirm the chosen account/channel and upstream revocations after an authorized lifecycle action. Account merge and deletion were not executed in this refresh.
Compliance Mappings
| Framework | Control | Mapping intent |
|---|---|---|
| SOC 2 | CC6.1, CC7.2 | Supports access and monitoring objectives |
| NIST SP 800-53 Rev. 5 | AC-2, IA-2, SI-12 | Supports configuration and access objectives |
| ISO 27001:2022 | A.5.15, A.8.9 | Supports access and configuration management |
Sources: Merging accounts, Recipe CLI commands, FAQ (retrieved 2026-11-05; no live validation).
2. API & Recipe Governance
2.1 Treat API Messages as Action-Capable Ingress
Profile Level: L2 (Walk)
Description
Use a separate Kitchen V2 key per reviewed automation and validate event admission before forwarding content. The entire JSON object becomes context for an assistant that can use email, calendar and connected integrations.
Rationale
Why This Matters:
- An API key holder can cause the agent to process instructions with the account’s connected authority.
- Webhook fields, source URLs and selected text can contain adversarial instructions even inside valid JSON.
Attack Prevented: Untrusted event content causing unintended messages, calendar changes or external actions.
Prerequisites
Explicitly approved automation and existing Kitchen V2 key supplied by a secret manager. Never create a key merely to test this guide.
ClickOps Implementation
- Open Kitchen → API Keys and review the key owner/purpose. For an authorized new workflow use a dedicated named V2 key; the legacy
pk_V1 webhook is deprecated and cannot be reused at the new endpoint. - Authenticate and authorize the originating event, restrict sources and fields, bound payload size and deduplicate/replay-control it before calling Poke. Treat the content as untrusted; prompt labels are not an access boundary.
- On compromise revoke the affected key and review connected-account actions. Avoid automatic retries after an ambiguous send: delivery may already have happened.
Code Implementation
The pack validates a small JSON object offline by default. Only an explicit --send makes one POST to the fixed HTTPS origin; it hides the bearer credential from argv, refuses redirects, bounds transport and validates the documented success field. Acceptance means delivery to Poke, not completed or authorized downstream work. No administrative read endpoint or first-party SDK was established; the vendor’s generic HTTP examples are not a separate SDK.
Code Pack: API Script
set +x
set -Eeuo pipefail
umask 077
unknown() { printf 'UNKNOWN: %s\n' "$*" >&2; exit 2; }
case "${HTH_PROFILE_LEVEL:-1}" in 2|3|4) ;; *) unknown 'HTH_PROFILE_LEVEL=2..4 required before payload generation or delivery' ;; esac
[[ $# == 1 || ( $# == 2 && "$2" == --send ) ]] || unknown 'usage: reviewed-message.sh FILE.json [--send]'
[[ -f "$1" && ! -L "$1" ]] || unknown 'payload must be a reviewed regular file, not a symlink'
command -v jq >/dev/null || unknown 'jq is required'
tmp="$(mktemp -d "${TMPDIR:-/tmp}/hth-poke-send.XXXXXX")" || unknown 'cannot create private temporary directory'
trap 'rm -rf -- "$tmp"' EXIT
# Snapshot once; validate and send the same bytes from the private directory.
cp -- "$1" "$tmp/payload.json"
[[ $(wc -c < "$tmp/payload.json") -le 65536 ]] || unknown 'pack policy limits payloads to 64 KiB (not a vendor limit)'
jq -se 'length==1 and (.[0]|type=="object" and length>0)' "$tmp/payload.json" >/dev/null 2>&1 || unknown 'payload must contain exactly one nonempty JSON object'
[[ ${2:-} == --send ]] || { printf 'PREVIEW ONLY: valid JSON; zero requests. Entire body can trigger connected-account actions.\n'; exit 0; }
command -v curl >/dev/null || unknown 'curl is required'
[[ -n ${POKE_API_KEY:-} && ${#POKE_API_KEY} -le 4096 && "$POKE_API_KEY" != pk_* ]] || unknown 'supply an existing Kitchen V2 key, not a legacy V1 key'
[[ "$POKE_API_KEY" != *[$'\r\n\t ']* && "$POKE_API_KEY" != *'"'* && "$POKE_API_KEY" != *\\* ]] || unknown 'invalid key characters'
# Do not log the payload or return body.
if ! status="$(printf 'header = "Authorization: Bearer %s"\n' "$POKE_API_KEY" | curl -q --config - \
--silent --show-error --request POST --proto '=https' --tlsv1.2 \
--connect-timeout 15 --max-time 60 --max-filesize 1048576 \
--header 'Content-Type: application/json' --data-binary "@$tmp/payload.json" \
--output "$tmp/response.json" --write-out '%{http_code}' \
'https://poke.com/api/v1/inbound/api-message')"; then
unknown 'delivery outcome uncertain; inspect account before any retry'
fi
[[ "$status" =~ ^2[0-9][0-9]$ ]] || unknown "HTTP ${status}; inspect account before retry; response withheld"
jq -se 'length==1 and (.[0]|type=="object" and .success==true)' "$tmp/response.json" >/dev/null 2>&1 || unknown 'unrecognized acknowledgment; inspect account before retry'
printf 'DELIVERED to Poke per API acknowledgment; downstream actions/completion are unverified.\n'
Validation & Testing
Run preview on synthetic content and verify no network request occurs. A live send would require separate action review and an existing key; none was made here. Validate key revocation in the actual account and provider actions during incident response.
Compliance Mappings
| Framework | Control | Mapping intent |
|---|---|---|
| SOC 2 | CC6.1, CC7.2 | Supports access and monitoring objectives |
| NIST SP 800-53 Rev. 5 | AC-6, IA-5, SI-10 | Supports configuration and access objectives |
| ISO 27001:2022 | A.5.15, A.8.9 | Supports access and configuration management |
Sources: Poke API, V2 keys and response contract (retrieved 2026-11-05; no live validation).
2.2 Review Shared Recipe Credentials and Existing Subscribers
Profile Level: L2 (Walk)
Description
Treat a published recipe as a release of instructions and, when selected, shared integration credentials. Review existing subscribers separately from new signups.
Rationale
Why This Matters:
- The recipe’s shared integration option lets consumers act without connecting their own account.
- Editing a recipe affects new signups, not existing users’ installed behavior.
Attack Prevented: Shared-account abuse and false assumptions that a recipe edit revoked existing access.
Prerequisites
Kitchen recipe owner and upstream account owner; approved public/private distribution audience.
ClickOps Implementation
- Open Kitchen → Create Recipe or edit the intended recipe. Review onboarding instructions, required integrations and whether each connection is personal or shared. Avoid shared production credentials.
- Before publishing, use a low-privilege dedicated connection and review what another subscriber can cause it to do. Inspect any published website/form ingress and its connected-account actions.
- Track recipe versions and subscribers through the available product workflow. On unsafe releases, notify affected users through an authorized process and revoke upstream shared credentials where necessary; editing the recipe alone does not update existing users.
Automation: The fetched recipe documentation provides Kitchen authoring and first-party CLI development tools, but no verified administrative API for forcibly updating/revoking all existing recipe installations. No invented subscriber-enforcement endpoint or native policy file is supplied.
Validation & Testing
For an authorized pilot compare a fresh signup with an existing installation after a benign edit. Review shared-account provider logs and ensure the planned rollback revokes actual upstream rights. No recipe was published or subscribed during this refresh.
Compliance Mappings
| Framework | Control | Mapping intent |
|---|---|---|
| SOC 2 | CC6.1, CC7.2 | Supports access and monitoring objectives |
| NIST SP 800-53 Rev. 5 | CM-3, AC-6, IA-5 | Supports configuration and access objectives |
| ISO 27001:2022 | A.5.15, A.8.9 | Supports access and configuration management |
Sources: Creating recipes and shared integrations (retrieved 2026-11-05; no live validation).
3. MCP & Local Exposure
3.1 Authenticate and Scope Custom MCP Servers
Profile Level: L2 (Walk)
Description
Require server-side authentication and least privilege for each custom MCP connection. Use Poke’s user identifier only as authenticated request context, never as a standalone authorization credential.
Rationale
Why This Matters:
- A custom server can expose sensitive tools and data to the assistant.
- A caller-supplied
X-Poke-User-Idheader alone cannot prove identity; this is a security inference from the documented header, not a vendor authentication guarantee.
Attack Prevented: Unauthenticated MCP access, cross-user data leakage and excessive upstream tool rights.
Prerequisites
Owner of the HTTPS MCP endpoint, reviewed tool inventory and supported bearer/API-key authentication.
ClickOps Implementation
- Open Integrations → Custom / integrations/new, provide the reviewed name and MCP URL and optional API key, then Create only after approving server-side authentication. Use a dedicated secret and do not embed it in URL queries, browser-prefill links or CLI history.
- On the server validate the configured bearer credential first, then bind user context to the authorized account/tenant. Reject missing/invalid authentication; do not trust a user-ID header from arbitrary callers.
- Limit exposed tools and upstream account permissions. Remove the integration and revoke its credential on retirement; deletion of the client definition alone does not revoke server access.
Automation: Native custom MCP creation is documented in the UI and first-party poke mcp add CLI. Credential-bearing writes are intentionally left to the reviewed interactive workflow; the reference examples include argument/query credential paths that this guide does not reproduce. No enterprise MDM/SSO control is inferred.
Validation & Testing
Test missing/invalid authentication and a synthetic cross-user request against an authorized test server before connecting. Confirm the server rejects unauthorized operations independently of assistant instructions. No MCP connection was made here.
Compliance Mappings
| Framework | Control | Mapping intent |
|---|---|---|
| SOC 2 | CC6.1, CC7.2 | Supports access and monitoring objectives |
| NIST SP 800-53 Rev. 5 | AC-3, AC-6, IA-5 | Supports configuration and access objectives |
| ISO 27001:2022 | A.5.15, A.8.9 | Supports access and configuration management |
Sources: Custom MCP servers, Integrations (retrieved 2026-11-05; no live validation).
3.2 Bound Local Development Tunnels
Profile Level: L2 (Walk)
Description
Expose only an explicitly reviewed loopback MCP service for the duration of an attended development task, and stop the Poke tunnel afterward.
Rationale
Why This Matters:
- A tunnel exposes local tools/data to a remote assistant; it does not start or secure the MCP server.
- Tool discovery refreshes periodically, so the current tool set may change while a tunnel is active.
Attack Prevented: Unattended local-service exposure and unintended tools becoming remotely callable.
Prerequisites
Trusted already installed Poke CLI, reviewed local MCP server and an authorized signed-in development account. No agent/package installation is needed to inspect the preview.
ClickOps Implementation
- Start the reviewed MCP server separately with least privilege and no unrelated listeners. Review its authentication and tool set.
- Use the documented Poke CLI → tunnel workflow with a loopback endpoint and reviewed name. Keep the terminal attended; tool synchronization is approximately every five minutes.
- Stop with Ctrl+C when finished and inspect the Poke integration state plus local listener. Revoke credentials if the endpoint or tools were exposed incorrectly.
Code Implementation
The wrapper previews an exact loopback-only tunnel invocation. Only --start runs the already installed first-party CLI; npm is offline and no package is downloaded. It does not start an MCP server, create credentials or make background persistence. This refresh exercised only stubs and preview mode.
Code Pack: CLI Script
set +x
set -Eeuo pipefail
unknown() { printf 'UNKNOWN: %s\n' "$*" >&2; exit 2; }
case "${HTH_PROFILE_LEVEL:-1}" in 2|3|4) ;; *) unknown 'HTH_PROFILE_LEVEL=2..4 required before preview or tunnel start' ;; esac
[[ $# == 2 || ( $# == 3 && "$3" == --start ) ]] || unknown 'usage: attended-tunnel.sh http://127.0.0.1:PORT/mcp NAME [--start]'
# Intentionally supported subset; no URL credentials, query secrets or arbitrary hosts.
[[ "$1" =~ ^http://(127\.0\.0\.1|localhost):([0-9]{1,5})/[A-Za-z0-9_/-]+$ ]] || unknown 'only a reviewed HTTP loopback endpoint without query/fragment is accepted'
port="${BASH_REMATCH[2]}"
(( 10#$port >= 1 && 10#$port <= 65535 )) || unknown 'port out of range'
[[ "$2" =~ ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$ ]] || unknown 'invalid tunnel name'
[[ ${3:-} == --start ]] || { printf 'PREVIEW ONLY: npx --no-install poke tunnel %s -n %s\n' "$1" "$2"; exit 0; }
command -v npx >/dev/null || unknown 'approved local poke package and npx required'
printf 'Starting attended tunnel; Ctrl+C stops it. MCP server must already be independently secured.\n' >&2
exec env npm_config_offline=true npm_config_yes=false npx --no-install poke tunnel "$1" -n "$2"
Validation & Testing
Preview an approved synthetic endpoint and reject external hosts/credential-bearing URLs. During a separately authorized live task confirm Ctrl+C closes exposure and review any calls already made. Do not call preview a security test of the actual tunnel service.
Compliance Mappings
| Framework | Control | Mapping intent |
|---|---|---|
| SOC 2 | CC6.1, CC7.2 | Supports access and monitoring objectives |
| NIST SP 800-53 Rev. 5 | AC-17, SC-7 | Supports configuration and access objectives |
| ISO 27001:2022 | A.5.15, A.8.9 | Supports access and configuration management |
Sources: Recipe development and tunnel lifecycle, MCP tunnel commands (retrieved 2026-11-05; no live validation).
4. Compliance Quick Reference
Mappings support control objectives; they are not a product benchmark or certification. The bounded November search found no product-specific prescriptive CIS/SCuBA baseline; gated/unpublished coverage is unverified.
| Framework | Objectives | Controls |
|---|---|---|
| SOC 2 | CC6 access, CC7 monitoring | All controls as mapped individually |
| NIST SP 800-53 Rev. 5 | AC/IA, CM, SC and AU families | See each control’s specific mapping |
| ISO 27001:2022 | Access and secure configuration | A.5.15, A.8.9 objectives |
Appendix A: Edition and Deployment Compatibility
| Surface | Applicability |
|---|---|
| Poke account and integrations | Supported account/consent features; upstream grant differences apply |
| Kitchen V2 API | Existing authorized V2 key; deprecated V1 is not substituted |
| Recipes | Shared credentials and existing-user update behavior require separate review |
| CLI / tunnel | Trusted preinstalled first-party package and supported local service; no automatic install |
| Devin enterprise controls | Do not configure Poke; private enterprise capabilities remain unverified |
Appendix B: References and Automation Coverage
The November source-first inventory records product naming, precise configuration evidence, six automation surfaces, read/write differences and retrieval failures. Unverified is not verified absence. The Code Pack contains native or documented first-party interfaces only. No GraphQL, fabricated SDK, generic SQL, or guessed enterprise console is supplied. No live evidence or maturity promotion is claimed.
Changelog
| Date | Version | Maturity | Changes | Author |
|---|---|---|---|---|
| 2026-11-05 | 0.1.0 | ai-drafted | Initial source-first 6-control guide with separate identity/deployment boundaries and offline-tested packs; live product verification unavailable. | Codex (GPT-6) |
Contributing
Report corrections through GitHub issues and the contribution guide. Share redacted version-specific evidence without tokens, account data or proprietary content.