T02 · Agent Memory Poisoning
- Location
dingtalk-command.py:72- Finding
Unauthenticated Persistent Mutation of Bot-Name Configuration
- Content
View full analysis
bool: config_file = Path(__file__).parent / "config.json" if not config_file.exists(): return False try: with open(config_file, 'r', encoding='utf-8') as f: config = json.load(f) bot_names = config.get('bot_names', []) if new_name in bot_names: return False bot_names.append(new_name) config['bot_names'] = bot_names with open(config_file, 'w', encoding='utf-8') as f: json.dump(config, f, indent=2, ensure_ascii=False) print(f"✅ Automatically saved new name: {new_name}") return True except Exception as e: print(f"❌ Failed to save name: {e}") return False ``` The persistence operation is invoked automatically while parsing messages: ```python extracted_name = extract_bot_name(message) if extracted_name and auto_save: save_bot_name(extracted_name) ``` ### Technical Analysis The command parser extracts an arbitrary mention from each incoming message and persists it into the skill's `config.json` file. The operation does not verify that the sender is an administrator, that the mentioned name belongs to the deployed bot, or that configuration learning has been explicitly approved. The value is only constrained by the mention extraction expression: ```python match = re.search(r'@([^\s,,]+)', message) ``` Consequently, an untrusted sender can supply a large number of unique names. Each value is appended to `bot_names`, written to persistent storage, and later incorporated into the regular expression used to remove bot mentions from future messages. Although names are escaped before being incorporated into that expression, preventing direct regular-e ...[truncated 1876 chars]- Remediation
View remediation
