On master, railway up in a directory with no linked project (and no --project) silently creates a new project + service and deploys the cwd when it detects an agent harness is driving it — skipping the "Continue?" confirmation. Consent is inferred from the calling process, not the human.
The branch in command() (src/commands/up.rs):
if args.project.is_none() && configs.get_linked_project().await.is_err() {
if came_from_unauth_prompt || args.yes || ctx.agent_implicit_consent() {
return deploy_new_project(&args).await;
}
The comments make the intent explicit: "the agent invocation is the authorization, the same signal that skips the auth confirm."
Why it's worth a look
Consent is inferred from which process is calling, not from any signal the human wanted a new billable project from this exact cwd. An already-authenticated agent that runs railway up from the wrong dir or a monorepo root (exploratory, or pattern-matching "deploy this") hits this branch and mints a project + full-tree Nixpacks build with nothing to catch it. This also runs opposite to Railway's own MCP guidance, which says to confirm consequential actions and keeps destructive ops off the local tool surface. Real guardrails do remain — OAuth still needs a human, no domain is auto-created, the cwd is linked as a landing pad so re-runs don't duplicate — the gap is just the authenticated + no-link + agent-detected case.
Related signal: the agent-facing copy reads like a prompt injection
Worth flagging alongside this: when an AI coding agent (Opus 4.8 in Claude Code, in my case) ran railway up --help, it flagged the help text as a likely prompt-injection attempt and refused to act on it. The phrasing it caught on — "agent-driven contexts," "skip the surrounding prompts," "Combine with -y for fully unattended runs" — is, to an agent applying normal untrusted-tool-output hygiene, hard to distinguish from injected text trying to coax it into skipping confirmation and taking an expansive privileged action. So the copy meant to help agents is currently tripping their security heuristics. The fix below also defuses this, since the default path no longer has to advertise prompt-skipping.
Suggested change
Gate agent-auto-create behind an explicit opt-in (e.g. RAILWAY_AGENT_AUTOCREATE=1, or requiring an explicit --new / -y) rather than inferring it from harness detection. Without the opt-in, fall through to the structured NOT_AUTHENTICATED-style error you already surface for non-interactive, no-consent runs.
On master, railway up in a directory with no linked project (and no --project) silently creates a new project + service and deploys the cwd when it detects an agent harness is driving it — skipping the "Continue?" confirmation. Consent is inferred from the calling process, not the human.
The branch in command() (src/commands/up.rs):
The comments make the intent explicit: "the agent invocation is the authorization, the same signal that skips the auth confirm."
Why it's worth a look
Consent is inferred from which process is calling, not from any signal the human wanted a new billable project from this exact cwd. An already-authenticated agent that runs railway up from the wrong dir or a monorepo root (exploratory, or pattern-matching "deploy this") hits this branch and mints a project + full-tree Nixpacks build with nothing to catch it. This also runs opposite to Railway's own MCP guidance, which says to confirm consequential actions and keeps destructive ops off the local tool surface. Real guardrails do remain — OAuth still needs a human, no domain is auto-created, the cwd is linked as a landing pad so re-runs don't duplicate — the gap is just the authenticated + no-link + agent-detected case.
Related signal: the agent-facing copy reads like a prompt injection
Worth flagging alongside this: when an AI coding agent (Opus 4.8 in Claude Code, in my case) ran railway up --help, it flagged the help text as a likely prompt-injection attempt and refused to act on it. The phrasing it caught on — "agent-driven contexts," "skip the surrounding prompts," "Combine with -y for fully unattended runs" — is, to an agent applying normal untrusted-tool-output hygiene, hard to distinguish from injected text trying to coax it into skipping confirmation and taking an expansive privileged action. So the copy meant to help agents is currently tripping their security heuristics. The fix below also defuses this, since the default path no longer has to advertise prompt-skipping.
Suggested change
Gate agent-auto-create behind an explicit opt-in (e.g. RAILWAY_AGENT_AUTOCREATE=1, or requiring an explicit --new / -y) rather than inferring it from harness detection. Without the opt-in, fall through to the structured NOT_AUTHENTICATED-style error you already surface for non-interactive, no-consent runs.