AELSHA™ Nehemvix Start a free guide

Sending code to an LLM safely: secrets, private repositories and what leaves your machine

Take the secrets out before the first model call, fetch exactly the commit you mean without running anything, keep access tokens off the command line and the disk, and know which service receives what.

Sending source code to a large language model is safe enough when you control three things: what the text contains, how you fetched it, and where the credentials went. Most leaks happen in the gaps between them.

What can go wrong

Repositories hold credentials more often than anyone admits: a test key in a fixture, a token in a CI file, a .env that was committed once and deleted later. Sent unredacted, a secret travels verbatim to a third party and may come back in the model's output.

The fetch is a risk of its own. A normal checkout writes files to disk, follows symlinks, runs hooks and applies filters, all under the repository author's control. And the credential that opens a private repository is more sensitive than the code it opens. Put it in a URL or on a command line and it ends up in logs and process lists.

None of this needs an attacker. It only needs a tool that was built for convenience first.

Know what leaves, and to whom

Start with an inventory, because "we send your code to an AI" is too vague to reason about. List every service that receives anything, what exactly it gets and when. A typical AI documentation or review tool has at least three receivers: the model provider, which gets the code in prompts; any lookup services, which should get package names and versions but never code; and the tool's own server, if there is one, which holds the code while it works.

Write the list down and show it to your users. Everything below is about making the first receiver's share as small and as safe as possible, and keeping the rest of the list true.

Redact secrets before the first call

Scan every file once, when it is read, before any prompt is built. Look for two kinds of secret: values with a known shape, such as cloud keys and Git host tokens, and assignments whose name says secret (password, api_key, client_secret) and whose value looks random rather than like a placeholder.

Three rules make redaction work in practice:

Watch the false positives too. Redacting enum values and header names such as auth_invalid or x-api-key makes the output worse without protecting anything.

Fetch one commit and run nothing

The safest way to read a repository is to never let it do anything. Instead of git clone, initialise an empty repository, fetch exactly one commit and read the files as blobs:

git init
git fetch --depth 1 <url> <sha>
git cat-file -p <sha>:<path>

No working tree is ever checked out, so symlinks, hooks, .gitattributes filters and path tricks have nothing to act on, and no repository code runs. Add -c options that switch off hooks, symlinks, file and local protocols, redirects, submodules and credential helpers, and set a low-speed limit so a slow server cannot hold the fetch open.

Two more habits close the remaining gaps. Resolve the host once, check that it is a public address and pin the fetch to that address, so a DNS answer that changes mid-fetch cannot send it to an internal service. And pin the commit at the first fetch: every later read gets exactly that commit, never the branch head, so the output always describes one consistent snapshot.

Tokens: used once, never stored

Ask for a read-only access token, use it for one fetch at one commit, and do not store it. How you pass it matters as much as whether you keep it. Never put it on the command line, where other processes can read it, in the URL, where logs keep it, or on disk. Git can take an extra HTTP header from environment variables, which keeps the token in the one process that needs it.

The same rule applies to model keys. On a server that many people use, refuse to start if provider credential variables such as OPENAI_API_KEY are set, because provider SDKs fall back to them silently and would bill the wrong account or mix up users' credentials.

A token used once is one answer to a wider question, and we wrote separately about who an agent acts as and on whose behalf.

What stays afterwards

Delete the source and any working copy when the job ends. Keep only what the user asked for, the output, plus derived data you can justify, scoped to its owner. Never let private code drift into test sets or examples. And if you trace your pipeline, record names, ids and counts, never code, prompts or keys.

A worked example: Nehemvix and a private repository

Nehemvix turns a repository into a documentation guide with the user's own model key. Its inventory is short:

Its scanner checks 14 named patterns, from private-key blocks and AWS access key ids to GitHub, GitLab and Slack tokens and passwords inside URLs, plus secret-named assignments with a Shannon entropy of at least 3.0 bits per character. A match becomes [REDACTED:<rule>] on the same line. A file over 2 MB, or one whose scan runs past 2 seconds, is withheld whole. A security review on 27 October 2026 found one pattern that backtracked on long input, and it was bounded on both sides.

Follow one planted key through. A hostile test repository carries an AWS-style key. At ingest the scanner replaces it with [REDACTED:aws-access-key-id], so it never enters a prompt. In every live run of that test on OpenAI, Anthropic and Google models, the key never appeared in the guide.

The token path was tested live on 3 November 2026: a refused token failed with one clear error line, and a private run produced a guide scored 99 with the token in none of the saved files. Traces, when we switch them on, follow the same rule, as how we watch Nehemvix explains.

A checklist

  1. Write down every receiver of data, and what each one gets.
  2. Redact before the first prompt, keep line numbers stable, and fail closed.
  3. Fetch by commit, never check out, never execute.
  4. Pin DNS, and refuse redirects and local protocols.
  5. Pass credentials through the environment, not command lines, URLs or files.
  6. Refuse ambient provider credentials on a server many people share.
  7. Delete the source when the job ends, and keep derived data scoped to its owner.

The user-facing version is on security and your data. The other half of the threat, text in the repository that tries to instruct the model, is covered in testing for prompt injection.

Learning this to build your own agent? AELSHA™ can help you design it.

Try it on a repository you know

Free to use with your own model key.

Start a guide