---
title: Regex guards
description: Deny-list patterns on copied files — the original "no AWS RDS in .env" incident, generalised.
---
# Regex guards
`[[bootstrap.guard]]` rules vet each file produced by stage 1 of the [bootstrap pipeline](/configuration/bootstrap) against a list of regex deny-patterns. A match triggers either an abort or a substitution from a known-good fallback.
## the origin story
The original incident: someone created a worktree from a repo with `.env` pointing at the **production** AWS RDS host, then ran `php artisan migrate:fresh --seed` in the worktree thinking it was the local DB. The migration ran against prod.
The fix was institutional: never copy a `.env` blindly across worktrees. The mechanism is `[[bootstrap.guard]]`.
## schema
```toml
[[bootstrap.guard]]
name = "no-aws-rds"
deny_patterns = ["amazonaws\\.com", "\\.rds\\."]
on_match = "seed-from-example" # or "abort"
example_file = ".env.example" # required when on_match=seed-from-example
```
| `name` | string | — | referenced by `[[bootstrap.copy]].guards = [...]` |
| `deny_patterns` | list of strings | `[]` | Rust regex patterns (`regex` crate syntax). Matches anywhere in the file are flagged. |
| `on_match` | string | `"abort"` | `"abort"` or `"seed-from-example"` |
| `example_file` | string | none | path (relative to main checkout) of the file to substitute when `on_match=seed-from-example` |
## wiring a guard into a copy
The guard runs only when a `[[bootstrap.copy]]` step references it by name:
```toml
[[bootstrap.copy]]
from = ".env"
to = ".env"
required = false
guards = ["no-aws-rds"] # ← referenced here
```
A guard with no copy references it is dead config — `gwm doctor` (check #2) does not flag this (yet), so audit by hand or run `grep guards .gwm.toml` to spot orphans.
## `on_match` semantics
### `abort` (default)
A match halts the entire bootstrap with `✗`. The worktree itself was already created (stage 1 succeeded), so gwm rolls it back: removes the worktree directory and the branch.
```
bootstrap report:
✗ guard no-aws-rds on .env
pattern 'amazonaws\.com' matched on line 12
→ bootstrap aborted, worktree rolled back
```
The user sees the offending pattern, the line, and the fact that nothing was left behind. Re-run is safe.
### `seed-from-example`
A match triggers a substitution: gwm overwrites the offending file with the contents of `example_file` (still relative to the **main** checkout, since the worktree is fresh and unlikely to have its own example). Reported as `!` (warning), pipeline continues.
```
bootstrap report:
! guard no-aws-rds on .env
pattern 'amazonaws\.com' matched on line 12
→ substituted from .env.example
```
Useful when `.env` is genuinely sensitive but you want the worktree to have **some** working config (e.g. local sqlite) — the substitution lands you in a known-safe baseline you can iterate from.
## regex syntax
Patterns use the [`regex` crate](https://docs.rs/regex) — Perl-ish, no look-around. Anchors:
- No anchor → matches anywhere in the file.
- `^…$` with the multi-line flag `(?m)` → matches per-line.
Common patterns:
```toml
deny_patterns = [
"amazonaws\\.com", # AWS endpoints
"(?m)^DB_PASSWORD=(?!$|\"\"$)", # any non-empty DB_PASSWORD line
"BEGIN .* PRIVATE KEY", # accidental SSH keys
"sk_live_[A-Za-z0-9]{20,}", # Stripe live secret keys
]
```
Backslashes must be doubled inside TOML strings. Use TOML's literal strings (`'...'`) for raw regex if you have many backslashes:
```toml
deny_patterns = ['amazonaws\.com', '\.rds\.']
```
## doctor coverage
`gwm doctor` check **#2** (`guard references resolve`) validates that every `[[bootstrap.copy]].guards = [...]` name points at an existing `[[bootstrap.guard]]`. Catches typos at config-time instead of waiting for the next `gwm create` to fail. See [Integrations → `gwm doctor`](/integrations/doctor).
## related
- [Bootstrap pipeline](/configuration/bootstrap) — where guards sit in the execution order
- [`.gwm.toml` schema](/configuration/gwm-toml) — full type reference