📅 Day 220 — Finding That an Empty Tool List Meant 'Inherit Everything', Not 'Deny All'
🔄 Topic
While enabling local, source-attributed conversation recall for Hermes, I found an easy-to-misread authorization setting: an empty WhatsApp tool list did not mean “no tools.” In that version of the platform, it inherited the globally enabled tools.
🎯 Goal
Make direct conversations searchable locally without allowing a contact-facing WhatsApp session to search a broader raw conversation archive.
🛠 What I Did
The implementation combined recall with explicit privacy boundaries:
- limited collection to active top-level user and assistant messages from approved CLI, Telegram, and WhatsApp sources;
- excluded system, tool, reasoning, delegated, and archived records from intake;
- kept source/channel labels, unverified participant identity, and generated-assistant labeling with the stored evidence;
- prevented participant statements from becoming automatic profile facts;
- discovered that
platform_toolsets.whatsapp: []inherited globally enabled MCP tools instead of removing them; - changed the contact-facing scope to the explicit deny marker
no_mcp, while preserving the owner’s normal access through the appropriate channels; - put a boundary verifier ahead of the intake job and stopped the refresh when the deployed tool boundary did not match the intended policy;
- verified the installed release, scheduled job, metadata-only intake counts, and filtered local-search behavior without exposing private snippets.
🔗 Key Cybersecurity Connections
This is a least-privilege lesson hidden inside configuration semantics. An apparently restrictive value is not a security control until its effective runtime behavior is checked. Defaults, inheritance, and “empty means inherit” rules regularly create authorization mistakes because the configuration looks safer than the evaluator actually is.
It is also a data-classification lesson. A system can retain conversation evidence for local retrieval without treating every sentence as an owner fact, a training example, or content accessible from every chat surface. Source attribution and retrieval scope are controls, not just metadata.
🔍 Investigation Questions
- Does an empty access list mean deny, inherit, or invalid in this exact runtime?
- Can a contact-facing channel retrieve information from other contacts?
- Are source claims labeled as evidence rather than silently promoted to facts?
- Does the deployed service enforce the same policy described in configuration?
- What stays retained if a source conversation is later changed or deleted?
🚨 Detection Opportunities
Watch for:
- an explicit-looking empty policy resolving to inherited global permissions;
- retrieval results without source/channel attribution;
- cross-contact search capability on a contact-facing session;
- a scheduler continuing intake after its access-boundary verification fails;
-
“memory” features that blur evidence, profile facts, and model training.
event=effective_toolset_check configured_value=[] effective_result=inherited_tools severity=high action=replace_ambiguous_default_with_explicit_deny
🧭 MITRE ATT&CK Techniques
No direct ATT&CK mapping claimed. The work concerns access-control evaluation and privacy-preserving local retrieval rather than a specific adversary behavior.
🗺 Visual Investigation Diagram
Approved conversation evidence
↓
Attributed, bounded local intake
↓
Configuration says WhatsApp toolset = []
↓
Runtime check: [] inherits global tools
↓
Replace with explicit no_mcp deny boundary
↓
Verify deployed toolsets before indexing
⚠ Challenges
The difficult part was not indexing messages. It was refusing to infer policy from a configuration shape that looked obvious. The runtime’s interpretation was the only thing that mattered.
📚 What I Learned
I learned that configuration is an input to authorization, not proof of authorization. For a privacy boundary, I need to verify the effective decision in the deployed process.
➡ Next Steps
- Keep effective-toolset checks with any future channel configuration change.
- Design any contact-aware retrieval feature around authenticated per-chat scoping, not broad archive access.
- Preserve clear retention and deletion documentation for collected local evidence.
🧠 Reflection
“Empty” sounds safe in ordinary language. In a policy engine it may be an overloaded value with the opposite result. That is why I want every important security setting to be tested in the same form the runtime consumes.
🧩 Lessons Learned
What worked
An explicit deny marker plus a deployed boundary verifier.
What could have gone wrong
Contact-facing WhatsApp sessions could have inherited broad retrieval capability despite a visually empty list.
Fix / takeaway
Never assume configuration syntax expresses the security policy you intend; inspect the effective runtime authorization result.
📈 Skill Progression Context
This gave me a concrete access-control and privacy-boundary case study: least privilege depends on effective permissions, evidence needs provenance, and a useful retrieval system must not become an unscoped archive.
😄 TL;DR
For Hermes, an empty WhatsApp tool list inherited global tools. Replacing it with an explicit deny boundary—and verifying the runtime result—was the real privacy control.
