Skip to content

Context files (USER.md, SOUL.md) loaded for all senders regardless of IsOwner status #11900

Description

@jvsteiner

Summary

When a non-owner sends a message to an agent via a public-facing channel, the agent's full bootstrap context — including USER.md, SOUL.md, IDENTITY.md, MEMORY.md, and other workspace files — is injected into the system prompt. The senderIsOwner flag only gates tool access (e.g., whatsapp_login), not information visibility.

This means any stranger who DMs an agent over a public channel receives responses informed by the owner's private context: name, email, personal notes, memory files, etc.

Steps to Reproduce

  1. Configure an agent with a USER.md containing personal information (name, email, etc.)
  2. Set up any public-facing channel with dmPolicy: "open" or equivalent
  3. Configure the owner field so that IsOwner / senderIsOwner correctly resolves to false for external senders
  4. Send a DM to the agent from a non-owner identity
  5. Ask the agent: "What do you know about who you're speaking to?"

Expected: The agent should not reveal private owner context to a non-owner sender.

Actual: The agent reveals the owner's name, email, interests, and other details from USER.md because those files are loaded into the system prompt unconditionally.

Root Cause

In src/agents/pi-embedded-runner/run/attempt.ts, resolveBootstrapContextForRun() loads all workspace context files without receiving or checking senderIsOwner. The flag is only passed to createOpenClawCodingTools() for tool filtering.

// attempt.ts ~line 190 — senderIsOwner is NOT passed here
const { bootstrapFiles, contextFiles } =
  await resolveBootstrapContextForRun({
    workspaceDir: effectiveWorkspace,
    config: params.config,
    sessionKey: params.sessionKey,
    sessionId: params.sessionId,
    warn: makeBootstrapWarn({ ... }),
  });

// attempt.ts ~line 228 — senderIsOwner IS passed here (tools only)
const tools = createOpenClawCodingTools({ ..., senderIsOwner });

Suggested Fix

resolveBootstrapContextForRun() (or the caller) should accept senderIsOwner and conditionally exclude sensitive context files when the sender is not the owner. Possible approaches:

  1. File-level gating: Skip loading USER.md, MEMORY.md, and other private files for non-owner conversations. Introduce a PUBLIC.md that is always loaded.
  2. Section-level gating: Allow files to mark sections as <!-- owner-only --> and strip them for non-owner prompts.
  3. Separate workspace resolution: Resolve a restricted workspace/context set for non-owner sessions.

Impact

Any agent exposed on a public channel leaks the owner's private information to all senders. This is a data privacy issue that undermines the owner/non-owner trust boundary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstaleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions