Back to skill

Security audit

LegalDoc AI

Security checks for vulnerabilities and agentic risk

Overview

This legal-workflow skill is mostly purpose-aligned, but it handles highly sensitive legal data with overstated security claims and under-disclosed local persistence and third-party data flows.

Install only after confirming how your firm handles privileged data. Treat research queries, alerts, cloud storage, and practice-management integrations as possible third-party disclosures, avoid putting client-identifying details in external searches unless approved, and do not rely on its deadline or statute-of-limitations output without attorney verification. If used, store the deadline database in a protected location and consider disabling or replacing features that lack encryption and confirmation controls.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
execution/deadline_tracker.py:145
Finding

Confidential Legal Matter Data Stored Without Encryption or Enforced File Permissions

Content
View full analysis

Vulnerability Details

File Location: execution/deadline_tracker.py:20-23, 145-184; templates/config.yaml:116-120
Vulnerability Type: Plaintext storage of sensitive legal matter data with insufficient permission enforcement
Risk Level: Medium

Vulnerable Code

python
# execution/deadline_tracker.py:20-23
DEFAULT_DB_PATH = os.environ.get(
    "LEGALDOC_DEADLINES_DB",
    os.path.expanduser("~/.legaldoc/deadlines.db")
)
python
# execution/deadline_tracker.py:145-184
class DeadlineDatabase:
    """SQLite-based deadline storage."""
    
    def __init__(self, db_path: str = DEFAULT_DB_PATH):
        self.db_path = db_path
        Path(db_path).parent.mkdir(parents=True, exist_ok=True)
        self._init_db()
    
    def _init_db(self):
        """Initialize database schema."""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS deadlines (
                id TEXT PRIMARY KEY,
                description TEXT NOT NULL,
                date TEXT NOT NULL,
                category TEXT NOT NULL,
                matter_id TEXT,
                matter_name TEXT,
                court TEXT,
                case_number TEXT,
                notes TEXT,
                alert_days TEXT,
                completed INTEGER DEFAULT 0,
                completed_at TEXT,
                created_at TEXT,
                source_document TEXT
            )
        """)
        
        cursor.execute("""
            CREATE INDEX IF NOT EXISTS idx_deadline_date 
            ON deadlines(date)
        """)
        
        cursor.execute("""
            CREATE INDEX IF NOT EXISTS idx_deadline_matter 
            ON deadlines(matter_id)
        """)
        
        conn.commit()
        conn.close()
yaml
# templates/config.yaml:116-120
security:
  encrypt_at_rest: false
  delete_after_processing: false
  anonymize_logs: true
  allowed_ip_ranges: 
...[truncated 2351 chars]
Remediation
View remediation

Remediation Suggestions

  1. Enforce restrictive filesystem permissions

    • Create ~/.legaldoc with mode 0700.
    • Create the database with mode 0600.
    • Validate and correct permissions on existing directories and database files.
    • Reject database paths that resolve to unsafe shared or world-writable locations unless the user explicitly overrides the warning.
  2. Encrypt sensitive data at rest

    • Use an appropriately reviewed encrypted database mechanism or encrypt sensitive columns before insertion.
    • Store encryption keys in an operating-system credential store or dedicated secrets manager rather than beside the database.
    • Define key rotation, recovery, and revocation procedures.
  3. Minimize persisted information

    • Avoid storing document-context excerpts as deadline descriptions unless required.
    • Store opaque matter identifiers instead of matter names where possible.
    • Make persistence of notes, case numbers, and source-document names optional.
    • Apply configurable retention and secure deletion policies.
  4. Improve disclosure and configuration

    • Clearly document that deadline records are persisted locally.
    • Do not present encryption at rest or privilege protection as enabled when encrypt_at_rest is false.
    • Warn users that custom paths and backups may expose confidential information.
  5. Add security tests

    • Verify directory and database modes after first use.
    • Test behavior under permissive umasks.
    • Test migration and permission correction for existing installations.
    • Confirm that sensitive fields are unreadable without the encryption key.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (38)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README promotes external legal research providers and broad third-party integrations for highly sensitive legal workflows, but it does not clearly warn users that documents, matter details, queries, or metadata may be transmitted to external services. In a legal context, this omission is especially dangerous because users may assume attorney-client privileged or confidential client data remains local, leading to unintended disclosure to vendors, cloud platforms, or research APIs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill advertises email alerts, Slack webhooks, practice-management integrations, and document-management connections, but it does not clearly warn users that sensitive legal documents, deadlines, matter metadata, or contact information may be transmitted to external services. In a legal context, this is especially risky because the data may be privileged, confidential, or regulated, and users could reasonably rely on the marketing-style privacy claims without understanding the external data flows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest requests file read/write, outbound HTTP access, and multiple API credentials while presenting a highly sensitive legal-document workflow, but it does not disclose how client documents, privileged content, or tokens are transmitted, stored, or shared. In a legal context, this omission is risky because users may expose confidential or regulated matter data to external services or integrations without informed consent or clear boundaries on data handling.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · execution/clause_extractor.py (reported line 182)May include surrounding context.

python
"risk_indicators": {
            "high": ["automatic termination", "requires consent"],
            "medium": ["notice required", "option to terminate"],
            "low": ["binding on successors", "no consent needed"],
        },
    },
}

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The load_document docstring says the function loads documents and notes production integration with parsing libraries, which suggests library-based parsing. However, when pypdf is unavailable, the implementation falls back to running the external pdftotext command via subprocess.run, introducing process execution behavior not reflected in the documentation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The statute-of-limitations logic is explicitly hard-coded to California defaults while accepting a jurisdiction parameter that is ignored, creating a strong risk that users will rely on incorrect legal deadlines for other jurisdictions. In a legal deadline tracker, this context makes the flaw more dangerous because inaccurate deadline computation can directly cause missed filing deadlines, malpractice exposure, or loss of legal rights.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The delete command permanently removes a deadline record from the SQLite database as soon as the command is invoked. Although a success message is printed afterward, there is no prior confirmation prompt or warning before this destructive operation occurs.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · execution/clause_extractor.py (reported line 238)May include surrounding context.

python
text += page.extract_text() or ""
        except ImportError:
            import subprocess
            result = subprocess.run(
                ["pdftotext", "-layout", file_path, "-"],
                capture_output=True, text=True
            )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · execution/document_summarizer.py (reported line 149)May include surrounding context.

python
text += page.extract_text() or ""
        except ImportError:
            import subprocess
            result = subprocess.run(
                ["pdftotext", "-layout", file_path, "-"],
                capture_output=True, text=True
            )

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code documentation and CLI expose summary_type, focus, and max_length as meaningful controls for summary generation, including choices like detailed, bullet, obligations, risks, and long output. In practice, summarize_document ignores those parameters and always calls generate_executive_summary, so the documented behavior contradicts the implementation rather than merely omitting a feature.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill sends user-supplied legal research queries to the external CourtListener API without any explicit user warning, consent flow, or privacy notice. Legal research queries can contain sensitive client matters, names, allegations, or litigation strategy, so transmitting them to a third party may create confidentiality, privacy, or compliance risks even though the transport uses HTTPS.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · execution/legaldoc.py (reported line 50)May include surrounding context.

python
return 1
    
    cmd = [sys.executable, str(script_path)] + args
    result = subprocess.run(cmd)
    return result.returncode

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This manifest configures outbound email notifications to specific addresses, which can transmit potentially sensitive legal deadline information outside the local system. In this YAML file there is no accompanying warning or disclosure that alerts may send case-related data via email.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The Slack alert settings include a webhook URL and channel, indicating outbound transmission to Slack when enabled. The file does not provide a user warning or disclosure about privacy and confidentiality implications of sending legal workflow data to a third-party messaging platform.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

These integration settings indicate that, when enabled, the skill can synchronize legal matters and deadlines with third-party practice management providers. The configuration template does not disclose that enabling these options may transmit sensitive client or case data to external systems.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The storage section supports providers such as Google Drive and Dropbox, which implies external storage or transfer of legal documents when configured. No warning is present here about the privacy, retention, or jurisdictional implications of storing sensitive files with third-party cloud services.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The CLI examples/documentation present legaldoc compare draft.pdf final.pdf --type redline as an available command, implying document comparison functionality. But the compare branch only prints 'feature coming soon' and exits without performing any comparison, so the documentation contradicts the actual behavior.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified with a lower-bound range instead of an exact pinned version, which makes builds non-reproducible and can cause the environment to pull in vulnerable or untested upstream releases. In a security-sensitive document-processing skill, parser libraries like pypdf are exposed to untrusted input, so version drift increases supply-chain and parser-risk exposure.

Content

Scanner excerpt · requirements.txt (reported line 9)May include surrounding context.

text
# Optional dependencies for enhanced functionality

# PDF parsing
pypdf>=3.0.0

# Word document parsing
python-docx>=0.8.11

Unverifiable Dependency: pypdf has 16 known advisory(ies) (CVE-2026-84310 (pypdf: Possible long runtimes/large memory usage when retrieving outlines); CVE-2026-48156 (pypdf: Possible long runtimes for zero-only width values in cross-reference stre); CVE-2026-24688 (pypdf has possible Infinite Loop when processing outlines/bookmarks) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding

pypdf has multiple known advisories, but because the manifest does not pin an exact version, it is impossible to determine whether deployments will receive a patched or vulnerable release. This is more concerning here because PDF parsers process potentially hostile documents and several advisories involve denial-of-service conditions such as excessive runtime, memory use, or infinite loops.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

python-docx is unpinned, so different installs may resolve to different versions with different security characteristics. Because document parsers often handle attacker-controlled files, leaving the exact installed version unspecified increases the chance of pulling a vulnerable release or breaking tested security assumptions.

Content

Scanner excerpt · requirements.txt (reported line 12)May include surrounding context.

text
pypdf>=3.0.0

# Word document parsing
python-docx>=0.8.11

# OCR support (for scanned documents)
pytesseract>=0.3.10

Unverifiable Dependency: python-docx has 2 known advisory(ies) (CVE-2016-5851 (Improper Restriction of XML External Entity Reference in python-docx); CVE-2016-5851 (python-docx before 0.8.6 allows context-dependent attackers to conduct XML Exter)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
93% confidence
Finding

python-docx has known XML-related advisories, and the lack of exact version pinning means the deployed environment may still resolve to an affected release. In a legal-document processing context, attacker-controlled DOCX files make parser weaknesses more relevant than they would be in a non-parser application.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

pytesseract is declared with a minimum version only, so installs are not deterministic and may pick up unexpected upstream changes. While this is not an exploit by itself, it weakens supply-chain control and can introduce vulnerable or incompatible releases into production.

Content

Scanner excerpt · requirements.txt (reported line 15)May include surrounding context.

text
python-docx>=0.8.11

# OCR support (for scanned documents)
pytesseract>=0.3.10
Pillow>=9.0.0

# Database (SQLite is built-in, but this adds connection pooling)

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

Pillow is unpinned, which means image-processing behavior and security fixes vary by installation. Since OCR/image workflows may ingest untrusted files, failing to pin this library increases exposure to known image parsing vulnerabilities and resource-consumption issues.

Content

Scanner excerpt · requirements.txt (reported line 16)May include surrounding context.

text
# OCR support (for scanned documents)
pytesseract>=0.3.10
Pillow>=9.0.0

# Database (SQLite is built-in, but this adds connection pooling)
# sqlite-utils>=3.30

Unverifiable Dependency: Pillow has 16 known advisory(ies) (CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding

Pillow has numerous advisories including resource-consumption and potential code-execution issues, but the manifest leaves the exact installed version unresolved. Because this skill may OCR scanned documents and therefore parse attacker-supplied images, uncertain Pillow versioning creates meaningful exposure.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

requests is not pinned, making network behavior and security posture dependent on resolver outcomes at install time. This can silently introduce versions with known flaws or behavioral changes affecting TLS, redirects, authentication, or proxy handling.

Content

Scanner excerpt · requirements.txt (reported line 22)May include surrounding context.

text
# sqlite-utils>=3.30

# API client improvements
requests>=2.28.0
urllib3>=2.0.0

# Date/time handling

Static analysis

No suspicious patterns detected.