Coding agents can read repositories, process issues and pull requests, execute commands and propose changes. That makes their security boundary part of the software supply chain.

The main risk is not that a model can be persuaded by a clever sentence in isolation. It is that untrusted content may influence a tool-enabled system that has more authority than the content should receive.

Treat repository content, issue text, web pages, generated code and model output as untrusted input.

Define the trust boundaries

A secure workflow distinguishes:

  • Untrusted data: issues, pull requests from forks, dependencies, web content, logs and generated output.
  • Agent instructions: scoped task requirements and project rules.
  • Capabilities: repository write access, shell execution, network access, secrets and deployment permissions.
  • Approval gates: human decisions for actions with production or external impact.

Do not let data sources grant themselves new capabilities. A README file or issue comment should never be able to override the workflow's permission model.

Apply least privilege

Give an agent only the permissions needed for its current task. A read-only investigation does not need repository write access. A test job does not need production deployment credentials.

For GitHub Actions, set explicit workflow permissions rather than relying on broad defaults:

permissions:
  contents: read

Grant additional permissions only to the job that needs them. Avoid exposing secrets to workflows triggered by untrusted fork pull requests. Review the security implications of pull_request_target before using it.

Isolate command execution

Never construct shell commands by concatenating untrusted strings. Prefer argument arrays and validate inputs against a narrow schema.

For Node.js:

import { spawn } from "node:child_process";

const result = spawn("git", ["status", "--short"], {
  shell: false,
  stdio: "inherit",
});

Do not pass arbitrary model-generated commands directly to a privileged shell. Use allowlisted operations, a disposable workspace and resource limits. Network access should be disabled unless the task requires it.

Validate data at boundaries

A model response is not trusted because it is valid JSON. Parse it, validate its schema and apply domain rules before using it.

import { z } from "zod";

const ChangeRequest = z.object({
  title: z.string().min(1).max(120),
  files: z.array(z.string().min(1)).max(20),
}).strict();

const request = ChangeRequest.parse(modelOutput);

Schema validation checks shape, not authorization. A valid file path can still point outside an allowed directory. Resolve paths and enforce the permitted root before reading or writing.

When rendering untrusted text, use safe text APIs and context-appropriate escaping. Do not interpolate raw strings into HTML, JavaScript or shell contexts. For JSON-LD, serialize data safely for an HTML script element; ordinary JSON serialization alone does not neutralise every HTML parsing hazard.

Protect secrets and logs

Use short-lived credentials where possible. Scope tokens to a repository and operation. Do not put secrets in prompts, source files, build artifacts or diagnostic logs. Masking is a last line of defence, not permission to print credentials.

Review third-party actions and dependencies by immutable version or commit where practical. Keep dependency updates and agent-generated feature changes separate so that review remains understandable.

Require approval for consequential actions

A sensible default is:

  • agent may inspect and propose;
  • agent may edit an isolated branch;
  • CI validates the patch;
  • a human reviews the diff;
  • deployment and external side effects require explicit authorization.

Automated remediation should be limited to low-risk, reversible changes with a clear rollback path.

Verify the controls

Test the workflow with hostile issue text, malicious filenames, malformed model output, unexpected tool responses and attempts to access secrets. Confirm that the system refuses operations outside its permissions.

Useful references:

A secure agent is not one that follows every instruction correctly. It is one whose capabilities remain constrained when its inputs are wrong or hostile.