Security, cost and team practices
Secrets in the workspace, network egress, dependency and prompt-injection risk, token spend, review gates, and standards for shared repositories.
Secrets, egress and injected instructions
| Risk | Concrete form | Control |
|---|---|---|
| Secret in the workspace | .env in the repo root during a run | Move it outside, or use a gitignored path and a scoped profile |
| Network egress | A dependency install posting data out | network_access = false |
| Prompt injection | Instructions in a README, an issue or a fetched page | Treat all read content as untrusted; never let it change permissions |
| Dependency supply chain | A package the agent added on its own | Review the manifest diff; require approval for new packages |
| Over-permissive MCP server | A write-capable tool available to every run | Enable per profile, least privilege |
| Persisted broad permission | A profile that disables approvals | Keep it container-only and out of shared dotfiles |
# check what a run could have read before you start it
ls -la .env* 2>/dev/null
git check-ignore -v .env 2>/dev/null || echo "WARNING: .env is not ignored"
find . -maxdepth 2 -name "*.pem" -o -name "id_rsa" -o -name "*.key" 2>/dev/null
# a minimal pre-flight that should be part of every team's workflow
cat > scripts/agent-preflight.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
fail=0
[ -z "$(git status --porcelain)" ] || { echo "dirty tree"; fail=1; }
[ -f .env ] && { echo "WARNING: .env present in the workspace"; fail=1; }
grep -q "^.env$" .gitignore || { echo "WARNING: .env not gitignored"; fail=1; }
[ "$fail" -eq 0 ] && echo "preflight passed" || exit 1
EOF
chmod +x scripts/agent-preflight.sh
./scripts/agent-preflight.sh- The agent reads files in the repository. Any credential stored there is in the context of a run, and any tool the run can reach may carry it further.
- Prompt injection is the sharp edge: text inside a file the agent reads is not an instruction from you, however it is phrased. Permissions must come from configuration, never from content the model read.
- Turning network access off is the single most effective egress control. Make installing dependencies a human step performed before the run.
- Scan the dependency diff of every agent-authored change. A new package is a supply-chain decision with a long tail, and it is easy to slip into a large diff.
Cost and attention
- Two costs, not one: token spend and senior review time. A large unrequested refactor can cost more in review than it saves in typing.
- Reasoning effort is the main per-run dial. Use the lowest setting that completes the task; reserve high effort for problems where the reasoning is the hard part.
- Scope controls spend more than any model setting. A task confined to three files uses a fraction of the context of a task that explores the repository for twenty minutes.
- Track spend per workflow rather than in aggregate: a monthly total tells you nothing about which task shape is the expensive one.
- The cheapest run is the one you did not need. For a mechanical edit with an obvious diff, editing by hand is often faster than writing the brief.
# log the shape and cost of every run so the numbers mean something
record_run() {
local label="$1"; shift
local start=$(date +%s)
codex exec --json "$*" > "agent-runs/${label}.jsonl" 2>&1
local status=$?
local end=$(date +%s)
printf '%s,%s,%s,%s\n' "$label" "$status" "$((end - start))" "$*" \
>> agent-runs/index.csv
}
mkdir -p agent-runs
record_run "lint-fix" "fix auto-fixable lint issues in src/"
column -s, -t agent-runs/index.csv | tail -5Report tokens only if the tool exposes them; otherwise track the proxy metrics that predict them: the duration, the number of files changed and the size of the final diff. Those are the numbers you can act on.
Team standards
| Standard | Rule | Enforced by |
|---|---|---|
| Clean tree | Never start a run on uncommitted work | A pre-flight script |
| Branch | One task, one branch | Branch protection on main |
| Commits | Small, reviewable, one idea each | Review and commit conventions |
| Instructions | Build and test commands in AGENTS.md | Code review of the file |
| Permissions | Conservative defaults; profiles for exceptions | Reviewed configuration |
| Attribution | Note agent involvement in the pull request | A pull request template |
| Review | A human reads the full diff, always | Branch protection with required reviewers |
| Credentials | Nothing sensitive in the workspace | Pre-flight check plus secret scanning |
<!-- .github/pull_request_template.md -->
## What changed
## How it was produced
- [ ] Written by hand
- [ ] Agent-assisted - task text and profile recorded below
## Verification
- [ ] `uv run pytest -q` passes locally
- [ ] The new test fails when the change is reverted
- [ ] `git diff --stat` contains only files related to this change
- [ ] No new dependencies without an explicit approval
## Review notes⚠️
The failure mode that matters at team scale is not a bad diff, it is a reviewer who stops reading. When agent-authored changes arrive faster than people can review them, mistakes reach main through review fatigue. Cap the rate of agent work to what the team can review properly, and make the cap explicit rather than aspirational.
FAQ
Can I paste production data into a task?
No. Anything in the task goes to the model provider and into your session logs. Use synthetic or redacted data in prompts and keep real records in the systems they came from.
How do we handle onboarding a new team member?
Give them the same repository instructions, the same conservative profile and the same review rules. The shared standard should live in version control so it applies to everyone instead of being personal knowledge.
Related
Approval modes and sandboxing Non-interactive runs and CI automation
Last refreshed 2026-09-18.