Cloning an untrusted repository is mostly safe, because git clone does not copy the remote's hooks or its local Git config. Opening that repository with an AI coding agent is a different question. The agent reads every file as possible instructions, it can run shell commands, and the repository can ship settings, hooks, MCP servers and install scripts that run with your account. It is safe only when you control those three things: where the agent runs, what secrets it can reach, and which project files you let it trust.
That is the short answer. The rest of this post goes through each piece in detail: what inside a repository can execute code or steer an agent, which of those things the major agents trust by default, how to set up a disposable environment that is boring to compromise, how workspace trust differs between an editor and an agent, what to check after a session, and which organisation settings stop a single cloned folder from rewriting your policy.
Key takeaways
git cloneitself does not bring the remote's hooks or.git/configwith it. The risk starts when something runs: an install script, a build, a test, a dev container, a Git command inside an archive you unpacked, or an agent following text it found in a file.- Agents treat repository text as context. A README, an
AGENTS.md, aCLAUDE.mdor a code comment can all carry instructions. The model's judgement is not a security boundary; the permission system, the sandbox and the operating system are. - Repository config is the larger risk. Claude Code and Codex both hold most project configuration until you trust the folder, but both have documented exceptions, and headless runs behave differently from interactive ones.
- Before you open unknown code, take secrets off the machine: no
.envfiles with live keys, no mounted~/.sshor cloud credential files, no long lived tokens in the environment. - The safest default is a throwaway container or VM with no network, a read only copy of the code, install scripts turned off, and the agent in a read only or plan mode.
- Organisation policy belongs in managed settings that project files cannot override, not in a file inside the repository.
Why this question is being asked now
Contractors pick up client codebases, maintainers review pull requests from strangers, and candidates get take home exercises. Agents change the risk in two ways: they read far more of a repository than a human would and treat it as guidance, and they act, running git status, npm install and test suites, often without anyone reading each command.
OWASP calls this indirect prompt injection: an LLM takes in outside content, such as websites or files, that contains instructions which change how the model behaves. OWASP says there may be no foolproof prevention, so mitigations aim to limit impact. That is the right framing here. You cannot rely on the agent noticing the trick. You can make sure that if it falls for it, very little happens.
Research round ups this month reported agents steered by a README line into sending secrets out, and Git configuration used to run code during routine Git commands. We could not open the primary disclosures, so we do not repeat their specifics. The mechanisms are documented in Git's and the agent makers' own manuals, and that is what this post relies on.
What in a repository can execute code or steer an agent?
Split the surface in two: files that run code when a tool processes them, and files that run nothing but can persuade an agent to run something.
Things that execute code
Git hooks. Git runs hooks from $GIT_DIR/hooks at set points; post-checkout even runs after git clone unless you pass --no-checkout. But Git's documentation says a new repository's hooks come from the local git init template, not from the remote, so a plain clone does not install the author's hooks.
Hooks become a risk in three other ways. A repository can ship a tracked hooks folder plus a setup script that points core.hooksPath at it, which is what hook manager packages do in a prepare script. An archive can include a complete .git directory, hooks and all. And an agent can be talked into changing core.hooksPath itself. We cover these in more depth in Can Git hooks run code on your laptop?.
Git configuration that names a command. Several keys in .git/config name a program for Git to run. The Git manual says core.fsmonitor, unless set to true, holds the pathname of a hook command used to find changed files, so it runs during ordinary commands like git status, which agents call constantly. core.sshCommand, core.pager and filter and diff drivers also name commands.
git clone writes a fresh config, so this is mostly an archive problem. Git refuses by default to parse the config of a repository owned by another user, and safe.directory exceptions are honoured only in protected configuration so a repository cannot switch the check off. But files you unpack yourself are owned by you, so in our reading that check will not fire.
Package manager lifecycle scripts. npm's documentation says a local npm install runs the project's prepare script, and preinstall, install and postinstall scripts run as packages install, including each dependency's own. Installing a Python source distribution runs its build backend. Makefile targets, Gradle and Maven plugins and go generate all run repository code when invoked.
Dev container definitions. A .devcontainer/devcontainer.json can declare lifecycle commands. The Dev Container specification says initializeCommand runs "on the host machine during initialization," while postCreateCommand and friends run inside the container. So a repository's own container definition can run a command on your host before any container exists. For untrusted code, use your own definition.
Editor tasks and debug configs. VS Code's .vscode/tasks.json and launch.json define commands; Workspace Trust makes both prompt for trust in an untrusted folder.
Agent configuration that runs code. The newest and least audited category:
- In Claude Code,
.claude/settings.jsoncan define hooks (shell commands on agent events), anenvblock and helpers such asapiKeyHelper. Subagents can carry frontmatter hooks and inline MCP servers; skills can declare hooks andallowed-tools. .mcp.jsonlists MCP servers; a local one is a process started on your machine.- In Codex,
.codex/config.tomland.codex/hooks.jsoncan define hooks and other settings.
Things that steer the agent
Instruction files. Codex concatenates AGENTS.md files from the project root down to the current directory, up to a default of 32 KiB. Claude Code loads CLAUDE.md files above the working directory at launch, loads subdirectory ones once it touches files there, and can read AGENTS.md too. These files exist so the agent follows them, which makes them a ready made channel in a repository you do not trust.
Claude Code's documentation says they are treated "as context, not enforced configuration." A malicious CLAUDE.md cannot grant itself permissions, and a defensive one cannot block an action. Enforcement lives in permission rules, hooks and the sandbox. When a project CLAUDE.md imports a file outside the working directory with @path, Claude Code asks for approval the first time.
Ordinary text. READMEs, issue templates, comments, test fixtures and the output of any command the agent runs can all contain instructions. No configuration file lists them, which is why isolation matters more than inspection.
Which of these do agents trust by default, and which need approval?
The defaults are not what most people assume. The table summarises each maker's own documentation. It describes behaviour, not which tool is safer.
| Repository content | Plain Git and npm | VS Code (Workspace Trust) | Claude Code | Codex |
|---|---|---|---|---|
Remote's hooks and .git/config | Not copied by git clone | Not applicable | Not applicable | Not applicable |
| Hooks and config inside an unpacked archive | Used by every Git command, unless ownership check fires | Not applicable | Git commands it runs use them | Git commands it runs use them; .git is write protected in workspace-write |
| Package install scripts | Run by default on npm install | Not applicable | Run if a Bash command you or the agent approve calls the installer | Run if the sandbox and approval policy allow the command |
| Editor tasks and debug configs | Not applicable | Prompt for trust in Restricted Mode | Not applicable | Not applicable |
| Project agent settings, allow rules | Not applicable | Restricted Mode disables agents in the workspace | Allow rules held until you accept the workspace trust dialog | Project .codex/ layer loaded only for trusted projects |
| Project hooks | Not applicable | Not applicable | Interactive: trust dialog comes first. Headless: used | Project hooks load only when the project layer is trusted |
| Project MCP servers | Not applicable | Not applicable | Separate approval prompt in interactive sessions. Headless: connected without asking | See maker docs for MCP specifics |
| Instruction files | Not applicable | Not applicable | Loaded as context | Loaded as context |
Claude Code: the trust dialog, and what runs without it
Anthropic's documentation says interactive sessions show a workspace trust dialog in a folder you have not trusted, and .mcp.json servers get their own approval prompt. Project permissions.allow rules and additionalDirectories apply only after you accept the dialog, which lists them first. deny and ask rules apply immediately because they only restrict.
The permissions page has a table, "What runs before you trust a folder", for two cases: you trusted only a parent folder, or you ran claude -p or the SDK in a folder never trusted.
- Hooks in settings files, the
envblock and helper commands such asapiKeyHelper, plus a project skill's hooks andallowed-tools, are used in both situations. permissions.allowrules are not used until you accept the dialog, and a headless run prints a warning instead.- Frontmatter hooks in a project subagent and inline MCP servers in subagent frontmatter are not used in either situation.
- Servers in
.mcp.json: if you trusted only a parent folder, Claude Code asks before connecting them. In aclaude -por SDK run in a folder never trusted, they are "connected without asking, approved or not."
Trust is keyed on the Git repository root, so a fresh clone inside a trusted folder gets its own dialog in interactive sessions. The interactive path gives you a decision point; the headless path does not.
Claude Code: what the default permission mode does
Anthropic says auto mode is the starting mode for interactive terminal and VS Code sessions: a separate classifier model reviews actions and blocks ones it judges unsafe, and your ask and deny rules still apply. Manual mode starts read only and asks before edits and commands other than built in read only ones such as ls and git status.
curl and wget are not auto approved by default, and Anthropic suggests permissions.deny to block them, noting that deny rules match command text, so sandbox network isolation is the stronger control. The working directory boundary is only a prompt: "a Bash command you approve can still write anywhere your user account can." And Read deny rules do not cover a Python or Node script that opens files itself.
Codex: sandbox modes and project trust
OpenAI's documentation lists three sandbox modes: read-only, workspace-write (the default for version controlled folders) and danger-full-access, which it calls "not recommended." Approval policies include on-request, never and granular. By default "the agent runs with network access turned off."
In workspace-write, .git stays read only, as do .agents, .codex and .aws where they exist, which stops a steered agent rewriting Git config or dropping a hook through the sandboxed shell.
Codex "loads project-scoped config files only when the project is trusted," and project hooks load only when that layer is trusted. Keys such as openai_base_url, model_provider and notify are ignored in project config. You can pin a path with trust_level = "untrusted" in user config. OpenAI also warns that "Prompt injection can cause the agent to fetch and follow untrusted instructions," and that monitoring does not replace sandboxing, permissions or review.
Instruction files are always read
Neither agent gates instruction text the way it gates hooks and allow rules. You can narrow what loads, but README text and comments have no switch. The control is what the agent may do after reading them.
How do you open untrusted code safely?
The goal: if the repository, or something it persuades the agent to do, tries to run code, read secrets or send data out, it finds nothing worth taking and no way to send it. Adjust names and images to your stack.
Step 1: Fetch without running anything, and look first
Clone without a checkout and list the files that matter before a working tree exists.
git clone --no-checkout https://github.com/example-org/example-project.git review-project
cd review-project
# Files that can run code or carry agent instructions
git ls-tree -r --name-only HEAD | grep -E \
'(^|/)(\.claude|\.codex|\.agents|\.vscode|\.devcontainer|\.githooks|\.husky)/|(^|/)(AGENTS|CLAUDE)\.md$|(^|/)\.mcp\.json$|(^|/)(package\.json|pyproject\.toml|setup\.py|setup\.cfg|Makefile|build\.gradle|pom\.xml)$'
# What runs on npm install
git show HEAD:package.json | jq '.scripts // {}'
# What the agent would be told
git show HEAD:AGENTS.md 2>/dev/null | head -100
git show HEAD:.mcp.json 2>/dev/null
git show HEAD:.claude/settings.json 2>/dev/null
If you were handed an archive instead of a URL, do not run Git inside it until you have read its config and hooks with plain file tools:
mkdir -p ~/quarantine/sample && tar -xzf sample.tar.gz -C ~/quarantine/sample
cat ~/quarantine/sample/.git/config
ls -la ~/quarantine/sample/.git/hooks
grep -nE 'fsmonitor|hooksPath|sshCommand|pager|editor|\[filter|\[diff' ~/quarantine/sample/.git/config
When you do need Git in such a folder, neutralise the obvious command bearing keys for that invocation:
git -c core.fsmonitor=false -c core.hooksPath=/dev/null status
Git's manual confirms core.hooksPath=/dev/null disables all hooks. Better still, delete the archive's .git and re-clone from the real source.
Step 2: Use a throwaway container you define, with no network
Use an image you choose, not the repository's devcontainer.json. Mount the code read only and drop network and privileges.
docker run --rm -it \
--name review-box \
--network none \
--read-only \
--tmpfs /tmp:rw,exec,size=2g \
--tmpfs /home/node:rw,size=512m \
--cap-drop ALL \
--security-opt no-new-privileges \
-v "$PWD":/src:ro \
-w /tmp \
node:22-bookworm bash
# Inside the container: work on a writable copy, never the original
cp -r /src /tmp/work && cd /tmp/work
No home directory is mounted, so there is no ~/.ssh, ~/.aws, ~/.npmrc token or agent credential store inside, and no route out for a successful injection. If the agent must reach a model API from inside, allow only that destination; Anthropic's reference dev container includes an init-firewall.sh allowlist script worth copying. For code you have real reason to distrust, use a VM, as Anthropic's guidance for untrusted content recommends.
Step 3: Install dependencies with scripts turned off
# npm: no lifecycle scripts from the project or any dependency
npm ci --ignore-scripts
# Python: fetch wheels only, so no build backend code runs
pip download --only-binary=:all: --no-deps -r requirements.txt -d /tmp/wheels
npm's documentation says ignore-scripts skips scripts in package.json files, except that explicit commands such as npm start and npm test still run theirs. npm also documents an allowScripts policy in package.json or .npmrc, but in an untrusted repository that policy is written by the author. Pass --ignore-scripts on the command line or set it in user config instead.
Step 4: Run the agent with the least capability that answers your question
Most first looks are questions, not edits, and need reading, not executing. For Claude Code, put a review profile at user scope or on the command line, never in the project:
{
"permissions": {
"defaultMode": "plan",
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl *)",
"Bash(wget *)"
],
"disableBypassPermissionsMode": "disable"
},
"sandbox": {
"enabled": true
}
}
Plan mode explores without editing source files. The sandbox is off by default until sandbox.enabled or /sandbox turns it on. To reject a named .mcp.json server in every session type, add it to disabledMcpjsonServers. For headless runs, Anthropic lists these flags for repositories you did not write:
claude -p "Explain what this repository does. List every command that runs on install, build or test, and any network destinations in the code." \
--bare \
--setting-sources user \
--settings '{"disableAllHooks": true}'
--setting-sources user skips the project's settings and .mcp.json. --bare skips project hooks, skills, subagents, plugins and .mcp.json servers, though the project env block still applies under --bare alone. disableAllHooks must come from --settings, because project settings take precedence over user settings and can set it back.
For Codex, mark the review path untrusted and keep the sandbox read only in your user config:
# ~/.codex/config.toml
sandbox_mode = "read-only"
approval_policy = "on-request"
# Documented in the config reference as projects.<path>.trust_level
[projects."/home/me/review/example-project"]
trust_level = "untrusted"
For VS Code, keep Workspace Trust on, open the folder in Restricted Mode, and send loose untrusted files to a restricted window:
{
"security.workspace.trust.enabled": true,
"security.workspace.trust.untrustedFiles": "newWindow"
}
Because subfolders inherit a trusted parent's trust, keep a separate ~/review folder you never trust.
Step 5: Only then, and only if needed, let it execute
If you need tests to run, grant execution inside the box with the network still off, and approve commands one at a time. If the agent proposes something that does not follow from your request, such as fetching a script or changing Git config, deny it and ask why. The answer often shows the instruction came from a file, not from you.
Choosing the right level of isolation
| What you need to do | Minimum setup | Agent mode |
|---|---|---|
| Read the code in a browser or on the hosting site | Nothing local | None |
| Ask an agent what the code does | --no-checkout clone, inspect configs, container without network | Plan or read only, project config not trusted |
| Install dependencies to explore types or docs | Container, install with scripts off, then cut network | Plan or read only |
| Run the test suite | Container or VM without network, no host mounts, your own image | Ask before every command, sandbox on |
| Build and run the application | VM, egress allowlist, short lived test credentials only | Ask before every command |
| Long term contribution after review | Normal workstation, but only after configs, hooks and scripts are reviewed and trust is granted on purpose | Your usual mode, with managed policy in force |
How does workspace trust differ between editors and agents?
In VS Code, Workspace Trust gates features. In Restricted Mode, editing works, but tasks, debugging, the terminal, workspace settings that point to executables and untrusted extensions are blocked or limited, and agents are disabled. Microsoft notes trust is shared with the Agents window, and subfolders inherit a trusted parent's trust.
In Claude Code, the trust dialog gates configuration that grants capability. It shows what the project's settings would allow and asks you to accept them. It does not stop the agent reading files or running commands under your permission mode, and it appears only in interactive sessions. A nested Git repository gets its own dialog.
In Codex, trust decides whether project scoped .codex/ config and hooks load, and Codex may start in read-only until you trust the working directory. Your own sandbox mode and approval policy decide what the agent can do either way.
The common thread: editor trust controls whether the tool runs the project's automation; agent trust controls whether the tool adopts the project's configuration. Neither decides whether the model believes what it reads. Only limiting what the agent can do handles that.
Watch the headless gap too. Claude Code's documentation says claude --bg in an untrusted directory shows the trust dialog first, and in a script exits with a "Workspace not trusted" error. A plain claude -p run never shows the dialog. Know which one your automation uses.
What should never be on the machine when you run an agent on unknown code?
Assume anything the agent's process can read, a malicious repository can get it to print, write or send. Then remove the valuable things.
- Live secrets in project files such as
.envorterraform.tfvars. Read deny rules do not stop a script that opens files itself, so remove the file or never mount it. - SSH keys and agent sockets. Anthropic's dev container guidance says to avoid mounting
~/.ssh. - Cloud credential files such as
~/.aws/credentials,~/.config/gcloudand~/.kube/config. Prefer repository scoped or short lived tokens. Claude Code's sandbox page notes a sandboxed command can read most of the machine by default, including~/.sshand~/.aws/credentials, unless you adddenyReadentries. - Package registry tokens in
~/.npmrc,~/.pypircor~/.docker/config.json. A publish token on a review box turns one bad repository into a supply chain incident for your users. - Source control tokens with write scope, such as a
GH_TOKENthat can push elsewhere. - Secrets in environment variables. Sandboxed commands inherit Claude Code's environment, "including any secrets in its environment." Start from a clean shell.
- The agent's own credentials. Anthropic warns that with prompts skipped, a dev container does not stop a malicious project exfiltrating what is inside it, "including the Claude Code credentials stored in
~/.claude." Use a separate, limited key for review work. - Browser profiles, password stores and production connections such as VPNs and database tunnels.
Anthropic's dev container page also says to use dev containers only with trusted repositories. On its own, a dev container is a convenience boundary. For untrusted code, add no network, no host mounts and no long lived credentials, or use a VM.
How do you review an agent's actions after a session on untrusted code?
Treat the end of a session like the end of a change window. You want to know what changed, what ran and what left the box.
Filesystem changes. If you used a container, Docker can list every file added, changed or deleted relative to the image:
docker diff review-box
Inside the working copy, compare against the commit you started from:
git status --porcelain --ignored
git diff --stat
git diff -- . ':(exclude)package-lock.json'
Git configuration and hooks. A steered agent's most persistent move is changing how Git behaves next time.
git config --local --list --show-origin
ls -la .git/hooks | grep -v '\.sample$'
git config --get core.hooksPath
git config --get core.fsmonitor
Any hook without the .sample suffix, or a hooksPath or fsmonitor value you did not set, needs an explanation.
Agent configuration. Check for new or changed .claude/, .codex/, .mcp.json, AGENTS.md, CLAUDE.md or .vscode/ files. A change there is an attempt to persist into the next session. Claude Code treats .git and .claude as protected paths, but bypassPermissions skips prompts even for those.
The transcript. Claude Code keeps session history under ~/.claude. Find the moment a request appeared that you did not make, and trace which file it came from. For teams, Anthropic documents OpenTelemetry metrics and ConfigChange hooks to audit settings changes.
Network. With no network there is nothing to check, which is the point. With an allowlisted proxy, a denied connection to an unfamiliar host is the clearest signal that something tried to send data out.
Then destroy the environment and rebuild from the image for the next repository.
What org-wide settings stop project configs from overriding policy?
A rule in a file inside the repository can be changed by whoever writes to that repository, including the author of the one you just cloned. Policy has to come from a layer the project cannot reach.
Claude Code
- Managed settings cannot be overridden by user or project settings, apart from a few documented keys. Deliver them through server managed settings or MDM; Anthropic warns that copying
/etc/claude-code/managed-settings.jsonin from a repository Dockerfile can be bypassed by anyone with write access. - Deny wins across scopes. A tool denied at any level cannot be allowed at another, and command line flags cannot override a managed deny.
allowManagedPermissionRulesOnlymakes managed settings the only source of permission rules, so project allow rules are ignored.permissions.disableBypassPermissionsModeandpermissions.disableAutoModeset to"disable"stop people switching prompts off.- Managed sandbox and managed MCP configuration enforce the sandbox, stop developers widening it, and restrict which MCP servers can run.
- Managed only instructions load only the organisation's
CLAUDE.mdat launch, leaving out project files and everyAGENTS.md. Subdirectory files still load on demand, so this narrows the channel rather than closing it.
Codex
- Managed configuration. OpenAI says that for local execution, MDM and legacy managed device requirements take precedence over Agent Security settings, which take precedence over the device's system requirements file.
- Project trust gates project config and hooks, and some keys are ignored in project config regardless.
Git, npm and the editor
- Protected Git config (system, global and command scopes) cannot be changed by a repository, and
safe.directoryis honoured only there. ignore-scripts=truein the user.npmrcon review machines and CI runners that handle untrusted code.- Workspace Trust stays on. Microsoft advises against disabling it.
Common mistakes
Trusting the parent folder. If you trusted ~/code in your editor months ago, every clone under it inherits that trust in VS Code. Keep untrusted work elsewhere.
Clicking through the trust dialog. It lists the project's allow rules so you can see what you are agreeing to. If a rule is unfamiliar, say no and read the file.
Running headless with default flags. claude -p shows no trust dialog and connects .mcp.json servers in an untrusted folder without asking.
Using the repository's own dev container. A container defined by the repository is a container defined by the attacker, and initializeCommand runs on your host.
Mounting your home directory "for convenience". One home or ~/.ssh mount undoes the container.
Relying on instruction files for safety. A CLAUDE.md line saying "never read .env" is context. A deny rule plus the sandbox is enforcement.
Assuming deny rules cover scripts. A deny on Read(./.env) does not stop a Python script opening the file. The sandbox, or not having the file, does.
Turning prompts off on a real laptop. Bypass modes are documented for isolated containers and VMs only.
Forgetting test scripts. --ignore-scripts covers the install. npm test still runs repository code.
Reusing the review box. Rebuild it for every repository.
Fix it without waiting for upstream
Opening an untrusted repository safely is about containment. The repository you decide to adopt afterwards, whether a client codebase, a fork or a new dependency, then becomes part of what you ship, and its vulnerable components become your exposure. That is where the gaps below start to matter.
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
Where Safeguard fits, and where it does not
No single tool answers "is this repo safe", so here is exactly where Safeguard helps.
What Safeguard does here. The Safeguard CLI can scan a directory, a container image or an SBOM file for its dependencies and match them against vulnerability databases: safeguard scan --dir . inside the same disposable container you set up above, with results written as JSON under ./output. That tells you what known vulnerable components a repository would bring with it before you adopt it, and reachability analysis tells you which of those your code actually calls. In the platform, you can see which of your projects already contain a given component and version, and policies and gates decide whether a build that includes it can ship. Safeguard's model and agent scanning also inventories agent configurations and skills as assets, so teams can see what agent setups exist across their estate and what tool access they declare.
The Safeguard CLI is itself an AI coding assistant that can edit code and run commands, so the advice in this post applies to it too. Its /permissions command offers Ask, Accept edits, Plan, Auto (the default) and Strict modes. For a repository you do not trust, switch out of Auto into Ask, Plan or Strict before you start, and run it inside the review box. The desktop and phone apps can send work to a computer running the CLI and let you approve each command, which suits a remote review VM.
What Safeguard does not do here. It does not inspect .git/config, hooks, AGENTS.md or README text for injected instructions. It does not sandbox your agent, contain a malicious install script, or replace the isolation steps above. Opening unknown code safely is still a job for containers, VMs, permission settings and managed policy. Safeguard's part is the dependency risk you inherit once you decide to keep the code.
If you want to try the CLI on a repository in your own review container, download Safeguard and follow the CLI documentation.
FAQ
Is it safe to git clone a repository from GitHub?
Mostly. Git's documentation shows a plain git clone does not copy the remote's hooks or local Git config, so cloning does not run the author's code. The risk starts when you install, build, test, open a dev container, or let an agent act on what it reads.
Can a README file hack my AI coding agent?
A README cannot execute anything. It can carry instructions the agent reads and follows, which OWASP calls indirect prompt injection. With network commands denied, secrets absent and execution sandboxed, a persuasive README has little to work with.
Does Claude Code run hooks from a cloned repository?
Interactive sessions show a workspace trust dialog first, and a fresh clone gets its own. In a headless claude -p or SDK run in an untrusted folder, Anthropic lists hooks in settings files among what still runs. Use --setting-sources user or --bare plus --settings '{"disableAllHooks": true}' for code you did not write.
Does Codex trust project config files by default?
OpenAI says Codex loads project scoped config and hooks only for trusted projects, and may start read only until you trust the directory. AGENTS.md is read as instructions regardless.
Is a dev container enough to open untrusted code?
Only one you define yourself, with no host mounts and no network. A repository's own definition can run initializeCommand on your host, and Anthropic's dev container page says to use dev containers with trusted repositories.
Does VS Code Restricted Mode stop AI agents?
Microsoft's documentation says Restricted Mode disables agents in that workspace and gates tasks, debugging and the terminal. Trust is inherited from a trusted parent folder, so keep untrusted code outside it.
Should I run npm install on a repository I don't trust?
Not with defaults. Use npm ci --ignore-scripts in a disposable container, and remember npm test still runs its script.
Can an AI agent read my .env file?
Yes, if it is reachable. Claude Code Read deny rules help, but Anthropic notes they do not stop a script that opens files itself. Keep live secrets off review machines.
Is it safe to use bypass permissions mode on untrusted repos?
Only in an isolated container or VM with no credentials. Anthropic documents that bypassPermissions skips prompts even for writes to .git and .claude. Organisations can disable it with permissions.disableBypassPermissionsMode.
How do I stop a cloned repo from changing my team's agent policy?
Put policy where project files cannot reach it: managed settings delivered by server or MDM, managed configuration for Codex, protected Git config, and user level npm config.
Related reading
- Why a cloned repo cannot approve its own MCP servers in Claude Code
- Can Git hooks run code on your laptop, and how to control them
- Are AI coding agent plugins and skills safe to install?
- Can AI agents escape their sandbox?
- Is Claude Code safe to use at work?
See how Safeguard would help
The first demo is a real Safeguard CLI session. It installs the CLI, opens the interactive terminal and asks it to fix a lodash CVE; the assistant reads the finding and the advisory, asks before each command, edits package.json, runs npm install and npm test only with approval, prints a summary and pushes nothing. It ends with /permissions, /model and /scan ., which is where you would switch out of Auto before working on a repository you do not trust.
Click through it at your own pace, or open it full screen.
The second demo sets up the Safeguard runner on your own machine, approves it with its device code, and then scans from the terminal. The same flow works inside a review VM or container that you control, so scanning an unknown repository's dependencies happens in the box rather than on your workstation.
Click through it at your own pace, or open it full screen.
The third demo connects Claude to the Safeguard MCP server with OAuth and shows choosing which tools Claude can use. It is a small example of the principle in this post: decide on purpose which tools an agent may call, rather than accepting whatever a configuration file offers.
Click through it at your own pace, or open it full screen.
Quick check
Does a plain git clone install the remote repository's Git hooks?
No. Git's documentation says hooks in a new repository come from the local template directory used by git init, not from the remote, and git clone creates its own fresh config. Hooks become a risk when a setup script points core.hooksPath at a tracked folder, when you unpack an archive that already contains a .git directory, or when an agent is talked into changing Git config.
Why are deny rules and instruction files not enough to protect secrets during an agent session on untrusted code?
Instruction files such as CLAUDE.md are treated as context, not enforced configuration, and Read deny rules do not stop a script that opens files itself. Enforcement comes from the sandbox and from not having the secrets on the machine at all.
Sources
- Claude Code documentation: Security
- Claude Code documentation: Configure permissions
- Claude Code documentation: Configure the sandboxed Bash tool
- Claude Code documentation: Development containers
- Claude Code documentation: How Claude remembers your project
- OpenAI Codex documentation: Agent approvals and security
- OpenAI Codex documentation: Advanced configuration
- OpenAI Codex documentation: AGENTS.md
- OpenAI Codex documentation: Configuration reference
- Development Containers specification: devcontainer.json reference
- Visual Studio Code documentation: Workspace Trust
- Git documentation: githooks
- Git documentation: git-config
- Git documentation: git-clone
- npm documentation: scripts
- npm documentation: config
- OWASP GenAI Security Project: LLM01 Prompt Injection
Last reviewed: 22 October 2026. Agent defaults change often; check each maker's documentation for the current behaviour of your version.