T02 · Agent Memory Poisoning
- Location
SKILL.md:43- Finding
Persistent Memory Content Can Influence Future Agent Sessions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a disclosed remote memory tool, but it gives agents persistent external memory and project deletion powers without enough trust-boundary and confirmation safeguards.
Install only if you intend to use Memstate as a third-party persistent memory service. Do not store secrets, regulated data, customer data, or private project details unless that data is approved for Memstate. Treat all recalled memories as untrusted reference material, and require explicit human review before using delete, recursive delete, or project delete commands.
SKILL.md:43Persistent Memory Content Can Influence Future Agent Sessions
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), headers=headers, method="POST")
try:
with urllib.request.urlopen(req) as response:
result = json.loads(response.read().decode("utf-8"))
print(json.dumps(result, indent=2))
return 0
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), headers=headers, method="POST")
try:
with urllib.request.urlopen(req) as response:
result = json.loads(response.read().decode("utf-8"))
print(json.dumps(result, indent=2))
return 0
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
url = f"{BASE_URL}/projects"
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req) as response:
result = json.loads(response.read().decode("utf-8"))
print(json.dumps(result, indent=2))
return 0
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), headers=headers, method="POST")
try:
with urllib.request.urlopen(req) as response:
result = json.loads(response.read().decode("utf-8"))
print(json.dumps(result, indent=2))
return 0
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
status_url = f"{BASE_URL}/jobs/{job_id}"
status_req = urllib.request.Request(status_url, headers=headers)
with urllib.request.urlopen(status_req) as status_resp:
status_result = json.loads(status_resp.read().decode("utf-8"))
status = status_result.get("status")
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), headers=headers, method="POST")
try:
with urllib.request.urlopen(req) as response:
result = json.loads(response.read().decode("utf-8"))
print(json.dumps(result, indent=2))
return 0
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), headers=headers, method="POST")
try:
with urllib.request.urlopen(req) as response:
result = json.loads(response.read().decode("utf-8"))
print(json.dumps(result, indent=2))
return 0
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), headers=headers, method="POST")
try:
with urllib.request.urlopen(req) as response:
result = json.loads(response.read().decode("utf-8"))
print(json.dumps(result, indent=2))
return 0
The top-level description presents the skill as memory storage/retrieval, but the documented behavior also includes destructive operations such as keypath deletion and whole-project soft deletion. That mismatch can mislead users or agents into invoking administrative data-destruction actions they did not expect from the advertised purpose.
The skill invokes Python scripts that require environment access and make outbound network requests, but it does not declare an explicit tool scope such as allowed tools or permissions. This weakens user and platform visibility into what the skill can do, making it easier for an agent to access secrets and transmit data externally without clear consent boundaries.
The skill encourages sending project facts, architecture decisions, and task summaries to an external REST API, but it does not prominently warn that potentially sensitive internal data will leave the local environment. In an agent setting, this can lead to unintentional exfiltration of proprietary or regulated information.
The authentication section tells users to set MEMSTATE_API_KEY but does not explain that the key is used for outbound requests to a third-party service and that submitted memory contents are transmitted there as well. This omission reduces informed consent around both credential use and data exposure.
The script includes capability to soft-delete an entire project, which is materially more destructive than ordinary memory retrieval or update operations implied by the skill description. In an agent context, this broad destructive action increases the risk of accidental or policy-bypassing data loss if the tool is invoked from ambiguous prompts or misaligned workflows.
The script performs a destructive project deletion immediately from a single command-line argument with no confirmation, dry-run, or secondary safeguard. In agent-operated environments, this makes accidental deletion substantially more likely, especially when user intent is ambiguous or the wrong project ID is supplied.
The file is explicitly designed to send data to an external service (https://api.memstate.ai/api/v1), which creates a real confidentiality boundary crossing. In the context of a memory skill for AI agents, that behavior is expected, but it is still security-relevant because agents may forward sensitive conversational, operational, or proprietary information to a remote API.
if not API_KEY:
print("Error: MEMSTATE_API_KEY environment variable is required", file=sys.stderr)
sys.exit(1)
BASE_URL = "https://api.memstate.ai/api/v1"
def remember_content(project_id, content, source=None, context=None):
url = f"{BASE_URL}/ingest"
The script transmits arbitrary user-supplied content and optional context to a remote third-party service, but the CLI behavior does not provide a clear, explicit warning at execution time that local data will leave the environment. In an agent-skill context, this is more dangerous because upstream prompts, documents, or memory items may contain secrets, internal notes, or regulated data that an operator may not realize are being sent externally.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not API_KEY:
print("Error: MEMSTATE_API_KEY environment variable is required", file=sys.stderr)
sys.exit(1)
BASE_URL = "https://api.memstate.ai/api/v1"
def set_memory(project_id, keypath, value, category=None, topics=None):
url = f"{BASE_URL}/memories/remember"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not API_KEY:
print("Error: MEMSTATE_API_KEY environment variable is required", file=sys.stderr)
sys.exit(1)
BASE_URL = "https://api.memstate.ai/api/v1"
def set_memory(project_id, keypath, value, category=None, topics=None):
url = f"{BASE_URL}/memories/remember"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not API_KEY:
print("Error: MEMSTATE_API_KEY environment variable is required", file=sys.stderr)
sys.exit(1)
BASE_URL = "https://api.memstate.ai/api/v1"
def set_memory(project_id, keypath, value, category=None, topics=None):
url = f"{BASE_URL}/memories/remember"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not API_KEY:
print("Error: MEMSTATE_API_KEY environment variable is required", file=sys.stderr)
sys.exit(1)
BASE_URL = "https://api.memstate.ai/api/v1"
def set_memory(project_id, keypath, value, category=None, topics=None):
url = f"{BASE_URL}/memories/remember"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not API_KEY:
print("Error: MEMSTATE_API_KEY environment variable is required", file=sys.stderr)
sys.exit(1)
BASE_URL = "https://api.memstate.ai/api/v1"
def set_memory(project_id, keypath, value, category=None, topics=None):
url = f"{BASE_URL}/memories/remember"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not API_KEY:
print("Error: MEMSTATE_API_KEY environment variable is required", file=sys.stderr)
sys.exit(1)
BASE_URL = "https://api.memstate.ai/api/v1"
def set_memory(project_id, keypath, value, category=None, topics=None):
url = f"{BASE_URL}/memories/remember"
This script takes arbitrary user-supplied memory content and sends it to a third-party remote service without any explicit user-facing notice at execution time. In an agent-skill context, this is risky because users or downstream agents may assume data stays local, causing accidental transmission of secrets, personal data, or proprietary context to an external API.
This Python file makes an HTTP POST request to an external service and transmits user-supplied values such as memory_id, project_id, or keypath. While the script name and argument help text imply history retrieval, there is no explicit user-facing warning, comment, or docstring noting that these identifiers are sent over the network to a third-party API.
No suspicious patterns detected.