Skip to content

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

@jvsteiner

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions