Back to skill

Security audit

Rapprochement paiements

Security checks for vulnerabilities and agentic risk

Overview

This accounting skill is mostly purpose-aligned, but it under-discloses sensitive plaintext sidecar files and has a vision-queue path issue that can process files outside the intended client folder.

Install only in a controlled accounting workspace. Treat generated .md, .extract.json, .vision.json, report, and temporary vision image files as sensitive financial records; exclude them from sync, backups, and source control unless intended. Review or patch path-containment checks before using resolve_vision.py on queues that anyone else can modify.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:75
Finding

Plaintext Copies of Sensitive Financial Documents Are Written Beside Source Files

Content
View full analysis
.md`).""" return Path(str(pdf_path) + ".md") def _write_transcription(pdf_path, text): """Écrit `.md` : la transcription texte brute du PDF (pdftotext/OCR), pour relecture humaine. Idempotent (n'écrase pas si déjà présent). La source de vérité reste le PDF — ce `.md` est une aide à la consultation.""" md = _md_path(pdf_path) if md.exists(): return try: body = text.strip() or "(aucun texte extractible — PDF scanné/photo, voir l'image source)" md.write_text( f"# Transcription — {Path(pdf_path).name}\n\n" f"> Texte brut extrait par `extract.pdftext()` (pdftotext `-layout` / OCR tesseract).\n" f"> Aide à la relecture ; la source de vérité reste le PDF.\n\n" f"```text\n{body}\n```\n", encoding="utf-8") except OSError: pass ``` The extraction result and raw text are also persisted in an adjacent cache: ```python if stamp is not None: try: save_json(_cache_path(pdf_path), {"_stamp": stamp, "fields": g, "text": text}) except OSError: pass ``` ### Technical Analysis Every processed invoice, expense receipt, or bank statement can produce two files adjacent to the original document: - `.md`, containing the raw OCR or PDF text. - `.extract.json`, containing extracted fields and the raw text. These files may include bank account identifiers, transaction histories, customer and employee identities, addresses, invoice references, and financial amounts. The files are written without explicitly applying restrictive permissions. Their effective permissions ...[truncated 2051 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/resolve_vision.py:78
Finding

Rasterized Financial Documents Persist in Temporary Storage

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/resolve_vision.py:53
Finding

Unvalidated Vision Queue Paths Permit Processing Outside the Client Root

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill description says to use the skill when the accountant wants a status update on payments and includes trigger examples like « où en sont les paiements ? » and « qui n'a pas payé ? ». These are broad everyday accounting questions rather than narrowly scoped invocation phrases, and the file does not provide negative examples or clearer activation boundaries to prevent unintended invocation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code file contains substantial natural-language instructions and output help text in French, including the module docstring and the _help guidance emitted for users. Because the skill forces a specific language without opt-in or an explicit documented regional justification, it violates the language/locale policy criteria.

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 · scripts/extract.py (reported line 152)May include surrounding context.

python
with tempfile.TemporaryDirectory() as td:
        prefix = os.path.join(td, "p")
        try:
            subprocess.run(["pdftoppm", "-png", "-r", str(dpi), "-l", str(max_pages),
                            str(path), prefix], capture_output=True, timeout=180)
        except Exception:
            return ""

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 · scripts/extract.py (reported line 158)May include surrounding context.

python
return ""
        for png in sorted(f for f in os.listdir(td) if f.endswith(".png")):
            try:
                r = subprocess.run(
                    ["tesseract", os.path.join(td, png), "stdout", "-l", "fra", "--psm", "6", "tsv"],
                    capture_output=True, text=True, errors="ignore", timeout=120)
                out.append(_tsv_to_layout(r.stdout))

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 · scripts/extract.py (reported line 180)May include surrounding context.

python
best = ""
    for args in (["-layout"], ["-raw"], []):
        try:
            r = subprocess.run(["pdftotext", *args, str(path), "-"],
                               capture_output=True, text=True, errors="ignore", timeout=30)
        except Exception:
            continue

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 · scripts/extract.py (reported line 1322)May include surrounding context.

python
os.makedirs(out_dir, exist_ok=True)
    prefix = os.path.join(out_dir, "page")
    try:
        subprocess.run(["pdftoppm", "-png", "-r", str(dpi), "-l", str(max_pages),
                        str(pdf_path), prefix], capture_output=True, timeout=120)
    except Exception:
        return []

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This Python file contains natural-language descriptions and runtime messages that consistently force French, including the module docstring and later console output. Under the language/locale policy, this is a violation unless the skill offers user opt-in or clearly documents that it is intentionally region- or locale-specific.

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 · scripts/resolve_vision.py (reported line 55)May include surrounding context.

python
def vision_kit(pdf_path, out_dir):
    """Appelle `extract.py --vision-kit` : rend les images des pages + squelette."""
    res = subprocess.run([PY, str(EXTRACT), str(pdf_path), "--vision-kit", str(out_dir)],
                         capture_output=True, text=True)
    try:
        return json.loads(res.stdout)

Static analysis

No suspicious patterns detected.