Skip to content

Security

June is a self-hosted orchestrator that spawns local CLI agents with broad filesystem access. This page is a level-set on what that means.

BoundaryTrusted?Notes
The machine June runs onYesJune assumes you control the host. Don’t run on shared hosts.
The local runner CLIYesThe CLI executes with your local user’s permissions.
Linear webhooksVerifiedHMAC-checked against JUNE_LINEAR_WEBHOOK_SECRET. Mismatched signatures are dropped.
Linear API responsesTrustedJune assumes Linear is non-malicious. Don’t run against a Linear workspace you don’t trust.
Issue / comment contentUntrustedComments are user-controlled and feed straight into the runner’s prompt. Prompt-injection risk.

The runner inherits the user’s filesystem permissions. With Claude Code’s --permission-mode auto, it can read and write anywhere the user can — including files outside the project. There is no chroot, no per-issue jail.

OpenCode is the exception: June injects an OPENCODE_PERMISSION profile that denies external-directory access and arbitrary bash by default. Override with LINEAR_CLAUDE_OPENCODE_PERMISSION.

If you need stricter isolation, run the orchestrator in a container or VM with the working tree bind-mounted in.

June reads secrets from environment variables only:

  • JUNE_LINEAR_API_KEY — Linear personal API key.
  • JUNE_LINEAR_WEBHOOK_SECRET — Linear webhook signing secret.
  • LINEAR_CLAUDE_ADMIN_TOKEN — bearer for /admin/*.

Never paste these into code, logs, Linear comments, or runner prompts. The orchestrator scrubs ANTHROPIC_API_KEY from the Claude child process so a stray env var doesn’t leak into the runner’s auth path — the runner uses its own login session instead.

The personal API key has the scope you grant it. June only needs:

  • Read on issues and comments (to fetch context).
  • Write on issues (to transition state) and comments (to post replies).

Avoid keys with admin scope unless you specifically need it. If you only operate against one team, a key scoped to that team’s read/write is sufficient — set JUNE_LINEAR_TEAM_KEY so June ignores webhooks from other teams.

Every incoming POST /webhook/linear is HMAC-verified against JUNE_LINEAR_WEBHOOK_SECRET before any DB write or routing decision. Mismatched or missing signatures are dropped with 401 Unauthorized. Dedupe runs on event id so a duplicated webhook delivery (Linear retries) does not re-trigger a session.

If you rotate the webhook secret in Linear, rotate JUNE_LINEAR_WEBHOOK_SECRET on the host and restart the service — old webhooks queued in flight will be dropped.

/admin/* endpoints require Authorization: Bearer $LINEAR_CLAUDE_ADMIN_TOKEN. If the token isn’t set, the endpoints return 404 (not 401) to avoid advertising their existence. The endpoints are powerful — they can terminate runs and reconcile state — so do not expose them publicly without the token set and do not run June with an empty admin token on a public ingress.

Comment bodies, issue descriptions, and image alt text all flow into the runner’s prompt. A Linear user with comment-write access can attempt to:

  • Steer the agent to read or write files it shouldn’t.
  • Steer the agent to make Linear API calls (via linear-action directives or by calling the API itself).
  • Steer the agent to install dependencies or run code.

June’s defense is shallow: it strips ANSI escapes, dedupes attachments, and constrains the linear-action action set. It does not pattern-match for injection attempts.

Mitigations:

  • Restrict who can comment. Lock the Linear workspace to trusted members only.
  • Run with the smallest filesystem footprint that works. Container, VM, dedicated host.
  • Audit linear-action blocks. The orchestrator strips them from comment bodies and appends an execution summary, so they’re visible in the thread.
  • Watch logs. logs/agent.log records every spawn, exit, state transition, and Linear API call.

The runner CLI has the user’s full filesystem and network access. On a shared host (multi-user dev box, jump host, etc.), that’s a foot-gun. Run June on a single-tenant machine.

  • No outbound calls beyond Linear’s API and whatever the runner CLI initiates.
  • No telemetry. No phone-home.
  • No update channel. You pull from main and restart.
  • No multi-tenancy. One orchestrator, one Linear workspace, one user.

If any of those are a deal-breaker, June is the wrong tool.