T09 · Insecure Skill Coding Practices
- Location
src/memory.py:103- Finding
Persistent Agent Memory Is Stored Without Explicitly Restrictive Permissions
- Content
View full analysis
Vulnerability Details
File Location:
src/memory.py, lines 103–105 and 112
Vulnerability Type: Plaintext sensitive data stored with umask-dependent permissions
Risk Level: MediumVulnerable Code
python if db_path is None: db_dir = Path.home() / ".agent-memory" db_dir.mkdir(exist_ok=True) db_path = str(db_dir / "memory.db") self.db_path = db_path self._init_db()The database is subsequently created or opened without enforcing its permissions:
python conn = sqlite3.connect(self.db_path)Technical Analysis
The default directory is created without an explicit restrictive mode, and the SQLite database is opened without verifying or enforcing file ownership and permissions. Their effective permissions therefore depend on the process umask and any pre-existing filesystem object at the path.
The database stores conversation-derived facts, lessons, personal entities, preferences, and arbitrary attributes in plaintext. In a multi-user environment with a permissive umask or incorrectly configured parent directory, another local account may be able to read this persistent context. If write access is available, that account may also tamper with the database and influence information recalled by the agent in later sessions.
The implementation also does not reject a pre-existing symbolic link at the default database path. Under an environment where an attacker can modify the memory directory, this may enable redirection to an attacker-controlled database or another writable target. Exploitation requires local filesystem access and inadequate surrounding permissions; no remote exploitation path is present in the reviewed code.
Attack Path
- An agent invokes
AgentMemory()with the default path. - The application creates
~/.agent-memoryandmemory.dbusing permissions derived from the process umask. - The agent stores sensitive conversation facts, behavioral lessons, preferences, or entity attributes in th ...[truncated 1233 chars]
- An agent invokes
- Remediation
View remediation
Remediation Suggestions
- Create the default directory with owner-only permissions:
python db_dir.mkdir(mode=0o700, parents=True, exist_ok=True) db_dir.chmod(0o700)- Securely create the database file with mode
0600before connecting, or immediately enforce that mode after creation:
python import os fd = os.open(db_path, os.O_CREAT | os.O_RDWR, 0o600) os.close(fd) os.chmod(db_path, 0o600)-
Use
lstat()and reject symbolic links for the default database path. Verify that both the directory and database are owned by the expected user. -
Apply equivalent validation to custom database paths or clearly document that callers are responsible for securing them.
-
Document that secrets, credentials, authentication tokens, and other highly sensitive values should not be stored in plaintext memory.
-
Where local-user isolation is insufficient, use an encrypted storage design with keys obtained from an operating-system keychain or another protected secret store.
-
Add tests that initialize the default storage under different umasks and assert directory mode
0700, database mode0600, expected ownership, and symbolic-link rejection.
