Files
PaperClipAI/doc/connections/SECURITY-THREAT-MODEL.md
DottaandPaperclip 3db2e6bdd2 feat(mcp) [split 8/8]: add e2e coverage and operator docs (#9563)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Governed MCP access spans contracts, runtime enforcement, adapters,
UI surfaces, and operator verification
> - The parity reference PR #9534 is too large for effective automated
or human review
> - The feature therefore needs a linear stack whose individual diffs
stay below the 100-file review limit
> - This pull request is split 8/8 and focuses on end-to-end coverage,
operator docs, evals, and release notes
> - The benefit is a standalone, testable review boundary while
preserving byte-for-byte parity at the top of the stack

## Linked Issues or Issue Description

- Related parity reference: #9534
- Problem: The complete stack needs discoverable browser scenarios,
operator guidance, threat modeling, eval coverage, and a parity proof
before merge.
- Proposed solution: Adds MCP user-story and Smoke Lab e2e suites,
docs/evals/release notes, the skill update, and the root e2e driver
script registration.
- Alternatives considered: keeping #9534 as one 403-file review, or
rewriting the feature to manufacture seams; both were rejected in favor
of path extraction plus compile-driven boundary moves.
- Roadmap alignment: this advances the existing governed MCP/tool-access
work already represented by #9534; it does not introduce a separate
roadmap initiative.
- Stack position: base branch is `pap10341-split/07-ui-apps-activation`.
- Merge policy: merge bottom-up, in order, only after the complete
eight-PR stack has been reviewed and the top-of-stack parity gate
remains empty.
- Requested review: QA for flag audit and e2e/browser acceptance;
Greptile on every PR.

## What Changed

- Adds MCP user-story and Smoke Lab e2e suites, docs/evals/release
notes, the skill update, and the root e2e driver script registration.
- Keeps this PR below 100 changed files and independently typecheckable.
- Preserves the final tree from #9534 when combined with the other seven
stack levels.

## Verification

- `pnpm typecheck`
- `node --check scripts/e2e-mcp-user-stories.mjs`
- `pnpm exec playwright test --config tests/e2e/playwright.config.ts
--list` — 43 tests discovered
- `git diff pap10341-split/08-e2e-docs
6b40e3876d9297105d4ec306e47e46d351c86172` — empty (0 bytes)

## Risks

- Browser suites depend on runtime services and environment setup; this
PR validates discovery locally while QA owns full flag-on/flag-off
execution.
- Stack risk: merging out of order can expose incomplete layers;
mitigate by following the documented bottom-up merge policy.
- Parity risk: later edits to an intermediate branch can drift from
#9534; mitigate by re-running the empty top-of-stack diff before merge.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex, exact model ID `gpt-5.4`; runtime-managed context
window; medium reasoning with repository, shell, Git, GitHub CLI, and
code-execution tools enabled.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] Internal references are omitted except the execution-plan link
explicitly required for this coordinated split stack
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge


## Stack Coordination

- Internal execution plan:
[PAP-13874](/PAP/issues/PAP-13874#document-plan)
- Parity reference: #9534
- Stack: #9556 → #9557 → #9558 → #9559 → #9560 → #9561 → #9562 → #9563
- Merge bottom-up only after full-stack review and an empty parity diff
at #9563.

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-14 15:48:57 -05:00

12 KiB

Connections Security Threat Model

Audience: engineers implementing or reviewing integration work on the Apps v2 substrate.

Post-read action: identify the mandatory authorization, credential, audit, and negative-test requirements before adding a new app, connection, transport, or provider wrapper.

Source: harvested from PAP-2359 and mapped onto the Apps v2 object model accepted in PAP-13211. The security decisions survived the Connections v1 retirement; the v1 implementation details did not.

Required Security Decisions

  1. Credentials live only in company_secrets. Connections store secret refs and redacted metadata. Raw OAuth access tokens, refresh tokens, API keys, app private keys, webhook secrets, and remote MCP bearer tokens must not live in connection config, plugin config, issue comments, activity logs, exports, or agent-visible payloads.
  2. Connection operations are company-scoped and brokered by Paperclip. Agents do not receive long-lived provider credentials. Plugin/provider code receives the minimum resolved material for a single invocation.
  3. Complete mediation is mandatory. Tool calls, sync jobs, webhooks, catalog refreshes that affect permissions, and broker projections re-check current connection status, secret state, profile/policy state, resource filters, and actor/company ownership at execution time.
  4. Default policy is deny-by-default. New connections grant no agent-visible access until an explicit profile/binding/policy path exists.
  5. Broad providers require resource filters. GitHub needs repo/org bounds, Slack needs channel/workspace bounds, Google Drive/Docs needs drive/folder/doc bounds, and equivalent broad providers need provider-specific bounds before agent grants are usable.
  6. Write/admin actions are explicit opt-ins. Read access does not imply write access. Destructive or newly changed write actions default to review.
  7. Revocation is immediate and failure-closed. Revoked secrets, disabled connections, expired policies, missing secret refs, or failed health checks block new execution and queued mutation work.
  8. External content is untrusted. Provider responses, chat messages, documents, webhook payloads, and remote MCP outputs may contain prompt injection and must not widen grants or bypass approvals.

Protected Assets

  • OAuth tokens, refresh tokens, app-installation tokens, API keys, webhook signing secrets, and remote MCP auth material.
  • Connection metadata: provider, workspace/account ids, resource filters, health state, transport config, and status.
  • Governance state: catalog entries, risk classes, quarantine state, profiles, bindings, policies, action requests, and trust rules.
  • Paperclip objects mutated by integrations: issues, comments, documents, projects, goals, activity rows, plugin entities, work products, and artifacts.
  • Agent runtime capability surface: the exact tools exposed into a heartbeat.
  • Audit trail: call events, action-request decisions, secret access events, webhook deliveries, and activity entries.

Actors And Trust Boundaries

Actors:

  • Board user or operator.
  • Company-scoped agent.
  • Plugin worker or provider adapter code.
  • External provider API.
  • External webhook sender.
  • Remote MCP server.
  • Attacker controlling a different company, compromised agent, compromised external account, malicious external document/message, or malicious upstream tool schema.

Trust boundaries:

  1. Board/API boundary: human-authenticated requests into the API.
  2. Agent/API boundary: bearer agent keys and run-scoped tokens.
  3. Server/plugin boundary: plugin workers are not the authorization boundary.
  4. Server/provider boundary: vendor APIs and remote MCP servers are outside the trust perimeter.
  5. Webhook boundary: inbound requests are attacker-controlled until signature validation and dedupe pass.
  6. External-content boundary: provider data is untrusted even when fetched through an authenticated connection.

Flow Requirements

Connection Creation And Authentication

Threats: spoofed OAuth callback, state replay, cross-company secret binding, forged app-installation metadata, forged remote MCP metadata, and token leakage.

Required controls:

  • OAuth start rows are short-lived and scoped to company, app/provider, requested scopes, creator, connection, and redirect URI. Use PKCE when supported.
  • OAuth callbacks reject missing, expired, replayed, mismatched-state, and mismatched-redirect requests.
  • API-key and app-installation flows write secret material to company_secrets first, then persist only refs and redacted account metadata on the connection.
  • Create/update routes validate same-company ownership for every referenced secret, app, connection, agent, user, project, routine, and issue.
  • Health and auth failures transition failure-closed: missing_secret, degraded, failed, auth_required, or disabled equivalents.
  • Error payloads and logs redact provider responses that may contain credentials.

Profile, Binding, And Policy Changes

Threats: non-admin actors widening access, IDOR against another company's agent or connection, implicit writes, and transient broadening during replacement.

Required controls:

  • Only authorized board/operator paths can create, update, or revoke connection grants, profiles, bindings, and policies in V1.
  • Every write validates same-company ownership across connection, principal, creator, referenced catalog entries, and target scopes.
  • Grant/profile replacement is atomic where possible. Avoid broad allow windows during multi-step updates.
  • Expired or disabled policy state is absent at read and execute time.
  • Write/admin access requires explicit catalog selectors or policy matches.
  • Broad provider grants without resource filters are rejected rather than interpreted as provider-wide access.

Catalog Refresh And Tool Exposure

Threats: upstream schema drift adding destructive tools, provider metadata spoofing, and agents seeing tools without current permission.

Required controls:

  • The server derives agent-visible tools from current profile, binding, policy, catalog, and connection state. Providers do not self-register tools directly into agent sessions without host filtering.
  • New or changed write/destructive catalog entries are quarantined until reviewed.
  • Catalog entries carry stable schema/version hashes so approvals and trust rules stop applying when schemas drift.
  • Agent tool-list routes return only tools that pass current company, profile, binding, policy, catalog status, and connection status checks.
  • Read tool output remains untrusted content and cannot mutate grants or profiles.

Tool Execution

Threats: BOLA/IDOR, excessive agency, prompt injection, secret disclosure, resource-filter bypass, and replaying old approval decisions.

Required controls at call time:

  • Actor belongs to the connection's company.
  • Connection is enabled and in a usable status.
  • Secret refs resolve to usable, non-revoked secret versions.
  • Effective profile exposes the requested catalog entry.
  • Policies allow the exact request or require an action request.
  • Tool/action risk does not exceed the allowed path.
  • Resource identifiers satisfy provider-specific filters.
  • Approval-derived trust rules match current catalog schema hash and exact reviewed argument shape.
  • Arguments and results are redacted before audit and agent-visible return.

Sync Jobs And Scheduled Ingest

Threats: queued work continuing after revocation, broad provider crawls, and storing data outside approved filters.

Required controls:

  • Each job run resolves connection state and re-checks profiles/policies/resource filters at run start.
  • Revocation, disablement, missing secret refs, or expired grants prevent future job starts.
  • Sync cursors are scoped to a connection and to the allowed resources.
  • Job config can narrow resource filters but never widen them.
  • Revoked/invalid scope failures emit audit/activity events and fail closed.

Webhooks

Threats: spoofing, replay, tampering, wrong-company routing, and unaudited provider-origin mutations.

Required controls:

  • Validate provider signature or authenticity material before dispatch.
  • Persist and dedupe delivery ids before mutation.
  • Resolve webhook secrets from company_secrets; never copy them into inline config.
  • Route webhook payloads only to the owning company/connection. Ignore request body ids until the signed/provider-authenticated envelope resolves the connection.
  • Apply resource filters before storing external mappings or mutating Paperclip.
  • For revoked/disabled connections, acknowledge where provider semantics require it, log the filtered/drop outcome, and do not mutate Paperclip state.

Import, Export, And Portability

Threats: secret disclosure, cross-company principal binding, and imports starting with broad active access.

Required controls:

  • Company export includes provider declarations, display metadata, redacted secret refs, profiles, and policy shape only. It excludes secret values and refresh tokens.
  • Import restores connections in an unusable state until destination-company secret refs are remapped and validated.
  • Imported profiles/bindings/policies become active only when referenced principals and connections resolve inside the destination company.

Required Negative Tests

Cross-company isolation:

  • Board user from company A cannot read/update/delete company B's app, connection, catalog entry, profile, policy, action request, or gateway session.
  • Agent from company A cannot list or invoke company B tools.
  • Create/update routes reject secret, agent, user, project, routine, issue, app, and connection ids from another company.
  • Webhooks for company A cannot mutate company B entities even if external ids collide.

Ungoverned or overbroad access:

  • Agent without an effective profile/binding cannot see the connection's tools.
  • Read-only grant/profile cannot invoke write/admin/destructive tools.
  • Missing catalog selector, disabled catalog entry, or quarantined catalog entry denies execution.
  • Empty resource filters are rejected for broad providers.
  • Tool execution against a disallowed repo/channel/folder/doc/project is denied even if the upstream token can access it.

Revocation and failure-closed behavior:

  • Revoked secret version, disabled connection, archived app, expired policy, and missing secret ref block execution immediately.
  • Queued sync/webhook work after revocation logs and does not mutate.
  • Health checks on invalid credentials do not leak provider secret material.

OAuth and callback integrity:

  • Missing, expired, mismatched, and replayed OAuth state is rejected.
  • Mismatched redirect URI is rejected.
  • Callback cannot bind credentials into a company other than the OAuth start company.

Webhook integrity:

  • Missing or invalid signature is rejected.
  • Duplicate delivery id is deduped without repeating side effects.
  • Valid webhook outside the resource filter is logged as filtered and dropped.

Redaction and agent safety:

  • API responses, activity rows, issue comments, action requests, exports, and tool-call audit never contain raw secret values.
  • External content cannot widen grants, create policies, or approve its own privileged tool call.
  • Remote MCP outputs are treated as untrusted content and cannot bypass ask-first gates.

Residual Risks

  • Plugin workers are trusted runtime code today, not a hard sandbox. Keep authorization in core server paths.
  • Remote MCP providers remain supply-chain and prompt-injection surfaces. Use narrow default profiles, schema hashing, changed-tool quarantine, and board-supervised rollout.
  • Provider OAuth/app-installation scopes may be broader than Paperclip resource filters. Paperclip must enforce the narrower internal filter.
  • High-risk writes still need good UX. Default them to ask-first, dry-run, or draft semantics until product copy and review flows are proven.