What you have now
Rover reads, writes, edits, searches, and runs commands. It asks before doing anything with a
side effect. It cannot leave its folder.
For a personal tool on your own machine, that is a reasonable place to be. It is not what a
product does, and the gap is worth naming precisely — partly so you know what to build if you
need it, and partly so you can read someone else’s agent and see what is missing.
The gap
| Guard | What it stops | Where yours stands |
|---|---|---|
| Path confinement | Reading and writing outside the project | Done — Lesson 3.5 |
| Permission prompt | Silent side effects | Done — Lesson 3.4 |
| Timeout | A hung command hanging the agent | Done — Lesson 3.3 |
| Process isolation | Everything else bash can reach |
Missing — needs a container or VM |
| Network egress limits | Data leaving, credentials being posted out | Missing |
| Secret redaction | Keys reaching the transcript, and the API | Missing |
| Audit log | Not knowing what it did an hour ago | Partly — Lesson 4.5 |
| Undo | A wrong edit being permanent | Missing — git is doing this for you |
Two of those deserve more than a table row.
Isolation is the one that actually bounds the damage
Everything else on that list narrows what the agent is likely to do. Isolation changes what is
possible.
Run the agent in a container with the project mounted and nothing else, and the worst case
stops being “your machine” and becomes “this container”. You have not made the agent better
behaved. You have made bad behaviour survivable, which is the only guarantee that does not
depend on your care.
This is why hosted agent platforms exist. Not because the loop is hard — you wrote the loop —
but because giving every session a clean, disposable, bounded machine is real infrastructure
work that nobody wants to do twice.
Secrets are the one people discover too late
Your .env file is in the project folder. safe_path allows it — it is inside the root.
So Rover can read your API keys, and the moment it does, they are in the transcript. The
transcript is sent to the API on every subsequent turn, and it is probably in your logs.
Two habits, starting now:
Refuse the obvious ones by name. A deny-list of .env, .pem, id_rsa, credentials,
.aws/ is not a security boundary, but it catches the accident, and the accident is the
common case.
Never let a secret into the transcript. Once it is in messages, it is resent every turn
for the rest of the session. There is no way to take it back out except starting again.
The honest summary
You have built the mechanism correctly. What separates this from a product is not
sophistication in the loop — it is the boring, expensive work around it: isolation, egress
control, redaction, audit, undo.
That work is not more advanced than what you have done. It is just more of it.
Your prototype is correct and unbounded. A product is the same loop with the blast radius
made small on purpose.
Try this before the next module
Add a deny-list to safe_path for .env, .pem, id_rsa, and anything under .git/.
Then ask Rover to “check the project configuration” and see whether it goes looking. Read the
refusal message you wrote. Would it tell a confused model what to do instead?