Back to skill

Security audit

Chronicle

Security checks for vulnerabilities and agentic risk

Overview

Chronicle is a coherent work-history tool, but it persistently captures broad private agent, file, prompt, command, and transcript data with several under-scoped exposure paths users should review carefully.

Install only if you are comfortable with a durable private work ledger. Review a dry run before enabling hooks, keep the ledger/CAS/spine private, avoid shell and remote hooks unless you explicitly need them, keep the canvas on loopback, inspect narration prompts before sending them to a model provider, and prefer pinning the Git install to a reviewed commit.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
src/chronicle/cli.py:233
Finding

Secret validation bypass through unfiltered standard input

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/chronicle/narrate.py:182
Finding

Broad transcript collection can transmit sensitive session data to an external model provider

Content
View full analysis
Path | None: """Claude Code keeps per-session transcripts under ~/.claude/projects/**. Reading the transcript is what separates this narrator from one guessing at intent from tool calls alone: the transcript contains the reasoning that produced them. """ base = Path.home() / ".claude" / "projects" if not base.exists() or not session: return None for candidate in base.rglob(f"{session}.jsonl"): return candidate return None def _transcript_block(session: str | None, budget: int) -> str: if not session or budget <= 0: return "" path = find_transcript(session) if not path: return "" try: data = path.read_bytes() except OSError: return "" note = "" if len(data) > budget: half = budget // 2 dropped = len(data) - budget data = data[:half] + b"\n...[transcript truncated]...\n" + data[-half:] note = (f"\n[NOTE: {dropped:,} bytes of the middle of this transcript were " f"omitted to fit the context budget. Do not treat the gap as inactivity; " f"the EVENT TRACE above is complete and authoritative.]\n") text = cap.redact_text(data.decode("utf-8", "replace")) return ("--- SESSION TRANSCRIPT (the reasoning behind the trace) ---" + note + "\n" + text) ``` ```python def call_model(prompt: str, timeout: int = 1800) -> str: if not MODEL: raise RuntimeError("Set CHRONICLE_NARRATOR_MODEL explicitly before narration") claude = os.environ.get("CHRONICLE_CLAUDE_BIN") or "claude" last = "" for attempt in (1, 2): proc = subprocess.run( [claude, "-p", "--model", MODEL], ...[truncated 3491 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/chronicle/canvas/server.py:155
Finding

Unauthenticated canvas can expose captured history when bound to a network interface

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:19
Finding

Installation instructions use an unpinned mutable Git repository

Content
View full analysis
Remediation
View remediation
' ``` 2. Prefer signed, immutable release tags and publish a verification procedure for the signing key. 3. Publish release artifacts with SHA-256 hashes and require users to verify them before installation. 4. Use a trusted package registry only if the project can prevent dependency confusion with the unrelated package mentioned in the documentation. 5. Add lockfiles or hashes for optional dependencies where deployment reproducibility is required. 6. Document the exact version or commit audited by the Skill. 7. Avoid recommending elevated installation privileges. 8. Advise users to run `chron install-hooks --dry-run` and inspect the deployed source before enabling persistent hooks. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (120)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The findings indicate installation and merging of hook commands into Claude/Codex configuration and behavior around git/zsh hooks, while the public description emphasizes history preservation rather than persistent agent/platform reconfiguration. Persistent config changes are risky because they can outlive the current task, affect future sessions silently, and are difficult for users to attribute or fully remove.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The findings indicate installation and merging of hook commands into Claude/Codex configuration and behavior around git/zsh hooks, while the public description emphasizes history preservation rather than persistent agent/platform reconfiguration. Persistent config changes are risky because they can outlive the current task, affect future sessions silently, and are difficult for users to attribute or fully remove.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The findings indicate installation and merging of hook commands into Claude/Codex configuration and behavior around git/zsh hooks, while the public description emphasizes history preservation rather than persistent agent/platform reconfiguration. Persistent config changes are risky because they can outlive the current task, affect future sessions silently, and are difficult for users to attribute or fully remove.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The findings indicate installation and merging of hook commands into Claude/Codex configuration and behavior around git/zsh hooks, while the public description emphasizes history preservation rather than persistent agent/platform reconfiguration. Persistent config changes are risky because they can outlive the current task, affect future sessions silently, and are difficult for users to attribute or fully remove.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The findings indicate installation and merging of hook commands into Claude/Codex configuration and behavior around git/zsh hooks, while the public description emphasizes history preservation rather than persistent agent/platform reconfiguration. Persistent config changes are risky because they can outlive the current task, affect future sessions silently, and are difficult for users to attribute or fully remove.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The findings indicate installation and merging of hook commands into Claude/Codex configuration and behavior around git/zsh hooks, while the public description emphasizes history preservation rather than persistent agent/platform reconfiguration. Persistent config changes are risky because they can outlive the current task, affect future sessions silently, and are difficult for users to attribute or fully remove.

Content

No source excerpt is available for this finding.

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding

Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 67)May include surrounding context.

python
# Paths whose CONTENT must never enter the store. The event is still recorded — knowing
# a secret file was touched is operational state — but with content omitted.
DENY_GLOBS = [
    "*.env", ".env", ".env.*", "*.pem", "*.key", "*.p12", "*.pfx", "*.keystore",
    "id_rsa*", "id_dsa*", "id_ecdsa*", "id_ed25519*", "*.ppk",
    "*credential*", "*secret*", "*.secrets", "*token*", "*password*",
    "*/.ssh/*", "*/.aws/*", "*/.gnupg/*", "*/.config/gh/*", "*/.netrc", "*netrc",

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 1279)May include surrounding context.

python
# Paths whose CONTENT must never enter the store. The event is still recorded — knowing
# a secret file was touched is operational state — but with content omitted.
DENY_GLOBS = [
    "*.env", ".env", ".env.*", "*.pem", "*.key", "*.p12", "*.pfx", "*.keystore",
    "id_rsa*", "id_dsa*", "id_ecdsa*", "id_ed25519*", "*.ppk",
    "*credential*", "*secret*", "*.secrets", "*token*", "*password*",
    "*/.ssh/*", "*/.aws/*", "*/.gnupg/*", "*/.config/gh/*", "*/.netrc", "*netrc",

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 1308)May include surrounding context.

python
# Paths whose CONTENT must never enter the store. The event is still recorded — knowing
# a secret file was touched is operational state — but with content omitted.
DENY_GLOBS = [
    "*.env", ".env", ".env.*", "*.pem", "*.key", "*.p12", "*.pfx", "*.keystore",
    "id_rsa*", "id_dsa*", "id_ecdsa*", "id_ed25519*", "*.ppk",
    "*credential*", "*secret*", "*.secrets", "*token*", "*password*",
    "*/.ssh/*", "*/.aws/*", "*/.gnupg/*", "*/.config/gh/*", "*/.netrc", "*netrc",

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/test_capture_invariants.py (reported line 242)May include surrounding context.

python
# Paths whose CONTENT must never enter the store. The event is still recorded — knowing
# a secret file was touched is operational state — but with content omitted.
DENY_GLOBS = [
    "*.env", ".env", ".env.*", "*.pem", "*.key", "*.p12", "*.pfx", "*.keystore",
    "id_rsa*", "id_dsa*", "id_ecdsa*", "id_ed25519*", "*.ppk",
    "*credential*", "*secret*", "*.secrets", "*token*", "*password*",
    "*/.ssh/*", "*/.aws/*", "*/.gnupg/*", "*/.config/gh/*", "*/.netrc", "*netrc",

Credential Access

High
Category
Privilege Escalation
Confidence
80% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 70)May include surrounding context.

python
"*.env", ".env", ".env.*", "*.pem", "*.key", "*.p12", "*.pfx", "*.keystore",
    "id_rsa*", "id_dsa*", "id_ecdsa*", "id_ed25519*", "*.ppk",
    "*credential*", "*secret*", "*.secrets", "*token*", "*password*",
    "*/.ssh/*", "*/.aws/*", "*/.gnupg/*", "*/.config/gh/*", "*/.netrc", "*netrc",
    "*/Keychains/*", "*.keychain*", "*/.docker/config.json",
    "*.kdbx", "*.jks", "*/service-account*.json", "*/.npmrc", "*/.pypirc",
]

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 71)May include surrounding context.

python
"id_rsa*", "id_dsa*", "id_ecdsa*", "id_ed25519*", "*.ppk",
    "*credential*", "*secret*", "*.secrets", "*token*", "*password*",
    "*/.ssh/*", "*/.aws/*", "*/.gnupg/*", "*/.config/gh/*", "*/.netrc", "*netrc",
    "*/Keychains/*", "*.keychain*", "*/.docker/config.json",
    "*.kdbx", "*.jks", "*/service-account*.json", "*/.npmrc", "*/.pypirc",
]

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 71)May include surrounding context.

python
"id_rsa*", "id_dsa*", "id_ecdsa*", "id_ed25519*", "*.ppk",
    "*credential*", "*secret*", "*.secrets", "*token*", "*password*",
    "*/.ssh/*", "*/.aws/*", "*/.gnupg/*", "*/.config/gh/*", "*/.netrc", "*netrc",
    "*/Keychains/*", "*.keychain*", "*/.docker/config.json",
    "*.kdbx", "*.jks", "*/service-account*.json", "*/.npmrc", "*/.pypirc",
]

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 71)May include surrounding context.

python
"id_rsa*", "id_dsa*", "id_ecdsa*", "id_ed25519*", "*.ppk",
    "*credential*", "*secret*", "*.secrets", "*token*", "*password*",
    "*/.ssh/*", "*/.aws/*", "*/.gnupg/*", "*/.config/gh/*", "*/.netrc", "*netrc",
    "*/Keychains/*", "*.keychain*", "*/.docker/config.json",
    "*.kdbx", "*.jks", "*/service-account*.json", "*/.npmrc", "*/.pypirc",
]

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 72)May include surrounding context.

python
"*credential*", "*secret*", "*.secrets", "*token*", "*password*",
    "*/.ssh/*", "*/.aws/*", "*/.gnupg/*", "*/.config/gh/*", "*/.netrc", "*netrc",
    "*/Keychains/*", "*.keychain*", "*/.docker/config.json",
    "*.kdbx", "*.jks", "*/service-account*.json", "*/.npmrc", "*/.pypirc",
]

# Content that looks like a live credential is masked in-place rather than dropping the

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · src/chronicle/capture.py (reported line 162)May include surrounding context.

python
r"\.pyc\b", r"\btarget/debug\b", r"\.DS_Store\b", r"\bcoverage\b", r"\.tox\b",
    r"\bvenv\b", r"\.venv\b", r"chron-selftest", r"pytest-of-",
    # Build output directories, matched as a PATH SEGMENT. An earlier version required a
    # trailing slash (`\bbuild\b/`), so `rm -rf ./build` — the single most common safe
    # destructive command there is — was denied. False positives are how a gate gets
    # switched off, so this pattern is deliberately generous about separators.
    r"(^|[\s/])\.?/?(build|dist|out|_build)/?(\s|$)",

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 1280)May include surrounding context.

python
check("cas verify", cas_verify(d1))

        check("deny .env", path_denied("/a/b/.env"))
        check("deny id_rsa", path_denied("/home/x/.ssh/id_rsa"))
        check("deny nested ssh", path_denied("/home/x/.ssh/config"))
        check("allow source", not path_denied("/a/b/main.py"))

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 1280)May include surrounding context.

python
check("cas verify", cas_verify(d1))

        check("deny .env", path_denied("/a/b/.env"))
        check("deny id_rsa", path_denied("/home/x/.ssh/id_rsa"))
        check("deny nested ssh", path_denied("/home/x/.ssh/config"))
        check("allow source", not path_denied("/a/b/main.py"))

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/chronicle/capture.py (reported line 1281)May include surrounding context.

python
check("cas verify", cas_verify(d1))

        check("deny .env", path_denied("/a/b/.env"))
        check("deny id_rsa", path_denied("/home/x/.ssh/id_rsa"))
        check("deny nested ssh", path_denied("/home/x/.ssh/config"))
        check("allow source", not path_denied("/a/b/main.py"))

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The declared capture set includes user prompts, tool usage snapshots, and other workflow details stored in a persistent ledger. In a skill framed as preserving operational history, that broad data capture can include sensitive prompts, secrets, internal file contents, and actions unrelated to the minimum needed purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The installer adds shell startup hooks that capture every interactive shell command, working directory, exit code, and duration into a persistent ledger. That exceeds the stated session-memory purpose of the skill and creates broad surveillance over unrelated user activity, including secrets typed at the shell and commands outside the agent workflow.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The shell hook is explicitly designed to log every interactive command to a persistent work ledger. Shell commands frequently contain credentials, tokens, database queries, hostnames, and operationally sensitive actions, so indiscriminate capture creates substantial privacy and security exposure.

Content

No source excerpt is available for this finding.

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

Scanner excerpt · src/chronicle/install.py (reported line 69)May include surrounding context.

python
BASH_HOOK = r'''
# ── chronicle capture ────────────────────────────────────────────────────────
# bash equivalent of the zsh hook. some hosts run bash, not zsh, so a zsh-only capture
# layer would silently record nothing on the machine that does the heaviest work.
# The DEBUG trap fires for every command in a compound statement, so a latch ensures
# one record per prompt rather than one per sub-command.
_chronicle_preexec() {

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The installer can deploy code and modify shell and agent configuration on remote machines over SSH/SCP, which materially expands the skill from local history preservation to remote administration. In this context, that is dangerous because it enables persistence and monitoring on additional systems without strong interactive approval boundaries in the code.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/chronicle/capture.py:1284

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/test_capture_invariants.py:243