Skip to content

Feature: add a fail-closed secure read-only execution profile #116

Description

@miticojo

Feature Description

Add an explicit, fail-closed secure read-only execution profile for repository scans.

The profile should be suitable for sensitive codebases (financial, healthcare, identity, or infrastructure repositories) where the scanner must retain the value of agentic cross-file analysis without giving an agent an unrestricted local execution boundary.

This is not a request for automatic vulnerability remediation. The first version should be analysis-only and should make the execution, filesystem, network, and credential boundaries observable and enforceable.

Motivation

deepsec is unusually useful when it can trace cross-file behavior, but that same capability makes the execution boundary part of the security product:

  • The README currently says to treat deepsec like a coding agent with full shell access on the environment where it runs.
  • The Claude backend allows Read, Glob, Grep, and Bash, uses permissionMode: "dontAsk", and deliberately sets failIfUnavailable: false for the local OS sandbox.
  • The local Claude path documents no additional filesystem or network restrictions.
  • deepsec.config.ts is loaded as executable TypeScript through jiti, and plugins can register agents, executors, notifiers, and other integrations.
  • Repository content, INFO.md, promptAppend, vendored dependencies, and generated reports can all become part of the agent's input or output.
  • The sandbox path is promising, but it uploads a tarball of the local working tree and depends on the correctness of the worker/proxy/egress boundary.

For an application such as a portfolio and financial-data product, the current choice is too binary:

  1. run locally and accept a broad shell/filesystem boundary; or
  2. use the remote sandbox path and accept code transfer plus a less transparent operational boundary.

A first-class secure profile would make the safe path explicit instead of relying on operator discipline and documentation warnings.

Proposed Solution

Introduce a profile that is explicit in the CLI and recorded in RunMeta, for example:

pnpm deepsec process \\
  --project-id mr-money \\
  --profile secure-read-only \\
  --network deny \\
  --credentials none

Suggested semantics for secure-read-only:

Filesystem

  • Mount the target repository read-only.
  • Allow writes only to a dedicated, separately mounted deepsec state/output directory.
  • Reject or clearly warn on repositories containing .env*, credential stores, SSH keys, cloud credential directories, or other sensitive paths unless the operator explicitly supplies a redacted/synthetic checkout.
  • Prevent traversal outside the declared repository root and deepsec state directory.
  • Keep the current tarball/path/symlink protections as hard requirements.

Process and tools

  • No arbitrary host shell access by default.
  • If the selected backend requires a shell, run it only inside an OS sandbox or microVM and fail closed when that isolation is unavailable.
  • Make the effective tool policy visible before the run starts and persist it in run metadata.
  • Disable remote/plugin installation paths by default for analysis runs.

Network

  • Default to deny.
  • For remote sandbox mode, allow only the configured model endpoint(s) and the minimum control-plane endpoints required to create/collect the worker.
  • Reject arbitrary user-supplied base URLs unless they are explicitly placed on an allowlist and shown in the preflight summary.
  • Add a test that verifies an agent cannot reach arbitrary hosts from the secure profile.

Credentials

  • Default to credentials: none for the agent process.
  • Keep credential brokering outside the worker where possible.
  • Never expose the raw model/API credential to the agent's Bash environment when the SDK supports an out-of-band transport.
  • Add a preflight report listing credential names and destinations, never values.
  • Make accidental forwarding of *_TOKEN, *_KEY, *_SECRET, *_PASSWORD, cloud credentials, and CI credentials a hard failure rather than a warning.

Prompt-injection boundary

  • Label repository files, INFO.md, promptAppend, issue text, and dependency content as untrusted data in the system prompt.
  • Add a documented policy that instructions found in scanned content cannot authorize tool use, network access, credential access, file writes, or scope expansion.
  • Preserve refusal/skip metadata and make it visible in the final report.

Auditability

Persist at least:

  • profile and isolation mode;
  • effective filesystem policy;
  • effective network policy;
  • tool allowlist;
  • credential broker mode and destination identifiers;
  • model/backend/version;
  • source checkout commit and hash;
  • whether the run was local, containerized, or remote sandboxed;
  • preflight warnings and failures.

Do not persist secret values or unrestricted chain-of-thought.

Acceptance Criteria

  • secure-read-only is an explicit profile, not an implicit collection of flags.
  • The profile fails closed when the required filesystem/process isolation is missing.
  • A secure-profile agent cannot write to the target checkout.
  • A secure-profile agent cannot read files outside the declared source root and dedicated state directory.
  • A secure-profile agent cannot reach arbitrary network destinations.
  • No host CI/cloud/SSH credentials are visible to the agent process.
  • Config/plugin loading is either isolated before execution or clearly excluded from the trusted scan boundary.
  • The effective policy is printed before execution and written to RunMeta.
  • Tests cover missing sandbox, symlink/path traversal, arbitrary egress, credential leakage, prompt-injection attempts, interrupted runs, and oversized/malformed worker artifacts.
  • Documentation explains what code leaves the local environment in remote sandbox mode and how retention/export is controlled.
  • The default behavior remains backwards compatible only if the current less-safe mode is explicitly labeled as such; the secure profile must not silently degrade to unrestricted local execution.

Alternatives Considered

“Just use Vercel Sandbox”

Useful as an implementation backend, but not enough as the product contract. Users still need an explicit policy, fail-closed behavior, egress visibility, credential guarantees, and audit metadata. The secure profile could use Vercel Sandbox, a local container, or another isolated runner behind the same contract.

“Just use Codex’s local sandbox”

The Codex path is better constrained than the local Claude path, but backend-specific behavior should not be the security policy. The guarantee should hold across supported backends or the secure profile should reject unsupported ones.

“Document that users should run it in a VM”

Documentation alone leaves the most important invariant outside the tool and is easy to violate in CI or on a developer laptop. A preflight plus fail-closed profile makes the boundary testable.

“Use traditional SAST instead”

Semgrep/CodeQL/secret scanners remain important and should complement this feature. They do not replace agentic cross-file reasoning, but they provide deterministic coverage and reduce the amount of trust placed in the agent.

Scope / Effort Estimate

Medium/Large. Likely areas:

  • CLI profile and preflight policy;
  • agent backend adapters;
  • local sandbox/container runner;
  • remote sandbox credential/egress policy;
  • tarball and artifact validation;
  • RunMeta schema and report/export surfaces;
  • adversarial integration tests;
  • security documentation.

A useful vertical slice would support one backend and one isolated runner first, then make other backends opt in only after the same acceptance tests pass.

Evidence from the current repository

Observed on commit 97ebd04b455a492dfd5b9ad86f2dd9cf8b05fa04:

  • README.md — documents full shell access, prompt-injection concerns, and the Vercel Sandbox model.
  • packages/processor/src/agents/claude-agent-sdk.ts — local sandbox uses failIfUnavailable: false; the agent has Bash and permissionMode: "dontAsk".
  • packages/processor/src/agents/codex-sdk.ts — contains useful environment allowlisting and separate handling for local versus in-VM execution, but also relies on backend-specific sandbox semantics.
  • packages/deepsec/src/load-config.ts — discovers and executes deepsec.config.ts through jiti.
  • docs/configuration.md — confirms executable configuration and plugin extension points.
  • docs/architecture.md — documents plugin-mediated agents, executors, notifiers, ownership, and persistent append-only state.
  • docs/data-layout.md — shows that findings, snippets, model/session metadata, git information, and reports are persisted locally and can be exported.
  • docs/faq.md — documents substantial scan costs and the fact that source snippets are sent to the configured LLM provider.

As a local verification signal, the repository built successfully and dependency audit reported no known production dependency vulnerabilities, but the unit suite on the same checkout had 2 failures out of 2,146 tests: a SIGINT shutdown-state test and an oversized-tarball timeout. This is not the basis for calling the project insecure; it is evidence that the isolation profile should ship with adversarial failure-path tests rather than only happy-path coverage.

Value

This feature would make deepsec materially more usable for teams that cannot run an unrestricted coding agent against their source tree. It would:

  • turn a documented risk into an enforceable contract;
  • reduce prompt-injection blast radius;
  • make local and remote execution comparable;
  • prevent silent sandbox degradation;
  • make security review results auditable;
  • enable adoption for finance, healthcare, identity, and infrastructure codebases without pretending that the agent is a trusted security boundary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions