Security model
mrsentry runs on code that someone else wrote and sends it to an LLM. It treats both the code and the model's output as untrusted.
MR content is data, not instructions
Prompts tell the model to treat code, comments, the MR title and the MR description as data and never follow instructions found in them. What the model can do is limited anyway: review gets only read-only tools, and every finding is checked against the real code before it's posted.
Sandboxed agent tools
- Every path is resolved and must stay inside the checkout, so symlinks can't escape. Writes to
.git/are refused. - Review gets only the read toolset. Only fix repair gets write and shell tools.
run_shellruns one allow-listed executable (fix.shell_allowlist) directly, with no shell, so pipes, redirects,;,&&and backticks are rejected. Output size and runtime are capped.gitis limited to read-only subcommands.
Credentials never reach subprocesses
Builds, lockfile tools, scanners and agent shell commands run with a scrubbed environment. Variables whose names look like secrets (TOKEN, SECRET, PASSWORD, KEY, AWS_, AZURE_, GITLAB, provider names and so on) are removed.
GitLab and AWS credentials are hard-denied, even if someone lists them in fix.build_env_passthrough. That covers MRSENTRY_GITLAB_TOKEN, GITLAB_TOKEN, the variable named in gitlab.token_env, CI_JOB_TOKEN, CI JWTs and ID tokens, the AWS keys, the session token and the web-identity token file.
The passthrough list exists for registry credentials that builds legitimately need, such as NEXUS_PASSWORD for settings.xml or NPM_TOKEN for .npmrc.
Git credentials stay out of URLs and logs
The token is passed to git as an HTTP header through GIT_CONFIG_* environment entries. It never appears in a clone URL, argv, .git/config or a log. Error output is scrubbed before it's printed. CI checkouts that embed the job token in origin get a separate, credential-free push remote.
Untrusted repository config
A repository's .mrsentry.yml comes from the MR branch, so whoever opens the MR controls it. mrsentry accepts only behaviour keys from it:
| Section | Allowed keys |
|---|---|
review | categories, min_severity, min_confidence, max_inline_comments, include, exclude, guidelines, extra_instructions, language, suggestions, skip_draft_mr, post_lgtm |
ecr | min_severity, ignore, include_os_packages |
fix | strategy, allow_major_upgrades, labels, draft_mr |
LLM endpoints and keys, GitLab settings, verify commands, shell allowlists, environment passthrough and cost limits are ignored with a warning. A malicious MR therefore can't send your code to its own endpoint or run its own commands as "verification".
Non-destructive by default
- Nothing is ever force-pushed to a human's branch. Bot-owned fix branches are updated with an explicit
--force-with-lease, checked against the tip the bot last read. - The MR head commit is checked before posting and before pushing. If it moved, the run stops with exit code 2.
- Protected source branches and fork MRs never get a direct push. Instead, mrsentry opens a fix MR or posts the patch as a comment.
- Use
--dry-runon any command to see exactly what it would do.
Data handling
- Code is sent only to the LLM profiles you configure. Choose Bedrock, Azure OpenAI or a self-hosted model to keep it inside your cloud.
- LLM transcripts are stored only when you set
output.save_llm_transcripts: true. mrsentry config showredacts secrets.