Skip to content

[SECURITY] pdf-autofillr-doc-upload v0.1.5 — Unauthenticated arbitrary file read via path traversal in /extract endpoint #55

Description

@EM-ShreyashGondane

Summary

Two compounding vulnerabilities in pdf-autofillr-doc-upload v0.1.5 allow an unauthenticated attacker to read arbitrary local files from the server via a single HTTP request to the /extract endpoint.

Package: pdf-autofillr-doc-upload
Affected versions: v0.1.5 (latest), all prior versions likely affected
Reported by: Farid Narimanov (independent security researcher) — coordinated disclosure


Vulnerability 1 — Auth bypass when AUTH_TOKEN is not set

File: pdf_autofillr_doc_upload/entrypoints/fastapi_app.py

def _check_api_key(provided: Optional[str]) -> None:
    expected = os.environ.get("AUTH_TOKEN")
    if not expected:
        return  # auth disabled
    ...

When AUTH_TOKEN is not configured in the environment (which is the default — no value is set out of the box), _check_api_key returns immediately without enforcing any authentication. Every endpoint protected by this check is publicly accessible with no credentials.


Vulnerability 2 — Path traversal / arbitrary file read in download_document()

File: pdf_autofillr_doc_upload/storage/local_storage.py

def download_document(self, source_path: str, local_dest: str) -> str:
    src = Path(source_path)
    dst = Path(local_dest)
    if src.resolve() != dst.resolve():
        dst.parent.mkdir(parents=True, exist_ok=True)
        shutil.copy2(str(src), str(dst))
    return str(dst)

The document_path field in ExtractRequest is a plain str with no validation, no allowed-directory check, and no path canonicalization. An attacker can supply any absolute path (e.g. /etc/passwd, SSH private keys, .env files) and the code will copy and process it — leaking its contents via the extraction pipeline response or job output endpoints. In deployments using an external LLM provider, the file contents are also sent to that provider as part of the extraction prompt.


Impact

These two vulnerabilities compound each other:

  • Default config = no auth required
  • No path restriction = any file readable

A single unauthenticated POST to /extract with a crafted document_path exfiltrates arbitrary server files.


Proof of Concept

# Auth bypass confirmed
from pdf_autofillr_doc_upload.entrypoints.fastapi_app import _check_api_key
_check_api_key(None)  # returns without error when AUTH_TOKEN not set

# Path traversal confirmed
from pdf_autofillr_doc_upload.storage.local_storage import LocalStorage
storage = LocalStorage(data_path="/tmp/safe_upload_dir")
storage.download_document("/etc/passwd", "/tmp/out.txt")
# => contents of /etc/passwd copied and readable

Recommended Fixes

Auth bypass:

  • Default AUTH_TOKEN to a required field — fail closed if unset rather than open
  • Or generate a random token on first run and log it to stdout

Path traversal:

  • In download_document(), validate that source_path.resolve() starts with the configured data_path
  • Add the same check at the API layer in ExtractRequest validation
# Example fix for download_document
def download_document(self, source_path: str, local_dest: str) -> str:
    src = Path(source_path).resolve()
    allowed_root = Path(self.data_path).resolve()
    if not str(src).startswith(str(allowed_root)):
        raise ValueError(f"Path '{source_path}' is outside the allowed directory")
    ...

Disclosure Timeline

  • Reported privately to Engineersmind security team by Farid Narimanov
  • Verified by internal security review
  • Fix in progress — coordinated public disclosure planned after patch release

/cc @Deewang-Mathur — please prioritize a patched release

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0: CriticalProduction broken / security breach — fix immediatelybugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions