Security

August 14, 2026 ยท View on GitHub

Trust Model

The DSRH Bundle is trusted profile configuration. The official MCP client starts the configured Python executable outside a model shell call, so Harness shell sandboxing does not automatically confine Python filesystem or network access. DSRH applies independent workspace and network policy inside the sidecar. Harness remains the authority for Agent filesystem and command execution.

Filesystem

Every user-supplied local path resolves against DSRH_WORKSPACE_ROOT, follows symlinks to its final target, and must remain within the canonical root. Existing inputs require real files or directories. Prospective outputs canonicalize every existing path component before creation, including symlinked artifact roots, while still allowing new nested directories. Tests cover .., absolute escape, and symlink escape across manifest, metrics, paper, and citation paths.

PDF size defaults to 100 MiB. Downloads stream into a bounded buffer. PyMuPDF parses born-digital documents without OCR or embedded-script execution. Malformed, encrypted, oversized, and scan-only documents produce explicit domain states.

Network

The sidecar builds provider URLs itself. Metadata endpoints are fixed to Crossref, OpenAlex, and arXiv; PDF download hosts are fixed to arxiv.org and export.arxiv.org over HTTPS. Redirects are disabled, metadata responses are limited to 5 MiB, timeouts and bounded retries apply, and HTTP 429 remains a structured failure. DSRH does not scrape Google Scholar, follow DOI redirects to publishers, or fetch arbitrary claim-support full text.

Commands

No MCP tool accepts or executes an arbitrary command. The native command renderer returns {command, executed:false}. Experiment execution must cross the existing Harness shell pipeline, including tools/pre-execute, monotonic guards, sandbox, approval, and job ownership. DSRH never uses os.system, never calls subprocess.Popen for training, and never exposes delete, process-kill, Git push, or shell tools.

The toy E2E test uses Python subprocess.run with a fixed repository-owned argv vector solely to exercise fixture metric collection; this code is outside dsrh_mcp, is not packaged, and accepts no model output.

Data and Credentials

Logs go to stderr and contain error types rather than request headers or secrets. DSRH does not read model credentials and does not inline DEEPSEEK_API_KEY. Citation cache files may contain public scholarly metadata. Reports and experiment provenance can contain project-sensitive information; repository owners decide what to commit.

Threat Review

ThreatControl
Path or symlink escapeCanonical containment checks before reads and writes
Command injectionNo MCP execution; typed argv rendered for later Harness-controlled execution
Malicious or large PDFSize bound, native parser error mapping, no OCR, no active content execution
Malformed BibTeX/YAML/JSONBounded parsers, Pydantic validation, structured domain errors
SSRF and redirectsFixed provider/host allowlists and redirects disabled
Unbounded downloadsStreaming byte cap and timeout
Provider 429/timeoutStructured visible status and bounded retry
Credential loggingNo auth/header/token logging
Plugin boot side effectsRuntime registers effects only; sidecar store opens lazily after MCP calls
Arbitrary subprocessNo production subprocess call in the Python package
Failed experiment suppressionAggregator reports requested, successful, failed, and missing runs