Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bin/lmab
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function banner() {
];
process.stdout.write("\n");
for (const [tone, row] of rows) process.stdout.write(` ${tone}${row}${color.reset}\n`);
process.stdout.write(` ${color.bold}${color.mint}${"LMAB".padStart(30)}${color.reset}\n`);
process.stdout.write(`\n ${color.dim}find the expensive routes. keep the evidence.${color.reset}\n`);
}

Expand Down
7 changes: 4 additions & 3 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ banner() {
printf ' %s%s%s\n' "$C3" $' | / _ \\ V V / -_) \'_| | \' \\ || | / _` | | | \'_ \\ | | |' "$R"
printf ' %s%s%s\n' "$C4" $' |_\\___/\\_/\\_/\\___|_| |_|_|_\\_, | \\__,_|_| |_.__/_|_|_|' "$R"
printf ' %s%s%s\n' "$C5" $' |__/ ' "$R"
printf ' %s%s%s\n' "$B$C4" $' LMAB' "$R"
printf '\n %sfind the expensive routes. keep the evidence.%s\n' "$D" "$R"
}
run() {
Expand Down Expand Up @@ -252,13 +253,13 @@ fi
section "3/3 · Start the audit"
ok "LMAB is ready"
if [ "$NO_LAUNCH" = "0" ]; then
say "Opening Claude Code in ${B}$TARGET_REPO${R}."
say "Opening Claude Code in ${B}$TARGET_REPO${R} with auto permissions."
say "The report will stay under ${B}.lmab/${R}."
PROMPT="Use the LMAB audit skill for this repository. Start immediately: scan the code locally, automatically seek narrowly relevant Anthropic billing totals in already-connected integrations, write .lmab/report.html and .lmab/share-card.svg, open the report, and do not edit application code or call a model provider."
if [ "$DRY_RUN" = "1" ]; then
run claude --plugin-dir "$SOURCE_DIR" "$PROMPT"
run claude --permission-mode auto --plugin-dir "$SOURCE_DIR" "$PROMPT"
else
exec claude --plugin-dir "$SOURCE_DIR" "$PROMPT"
exec claude --permission-mode auto --plugin-dir "$SOURCE_DIR" "$PROMPT"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 AI agent launched with automatic permission approval bypasses user confirmation for all actions

The installer now launches Claude Code with --permission-mode auto (install.sh:261), which automatically approves all permission requests (file writes, shell commands, network access, etc.) without user confirmation. The only constraint on Claude's actions is the natural-language prompt instruction to "not edit application code or call a model provider" (install.sh:257), which is not an enforceable security boundary. If the agent misinterprets the prompt or encounters an adversarial prompt injection in scanned files, it could perform destructive file operations or execute arbitrary commands with the user's full privileges.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

fi
else
say "Run ${C4}lmab audit .${R} when you are ready."
Expand Down
25 changes: 25 additions & 0 deletions tests/installer.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,31 @@ test("dry-run shows the complete bounded install without writing", () => {
}
});

test("launches Claude Code in auto permission mode", () => {
const root = mkdtempSync(join(tmpdir(), "lmab-installer-launch-"));
const fakeBin = join(root, "bin");
try {
mkdirSync(fakeBin, { recursive: true });
const fakeClaude = join(fakeBin, "claude");
writeFileSync(fakeClaude, "#!/bin/sh\nexit 0\n");
chmodSync(fakeClaude, 0o755);

const result = run(
"bash",
["install.sh", "--yes", "--dry-run", "--install-dir", join(root, "home")],
{
cwd: process.cwd(),
env: { ...process.env, PATH: `${fakeBin}:${process.env.PATH}` },
},
);

assert.match(result.stdout, /Opening Claude Code .* with auto permissions/);
assert.match(result.stdout, /claude --permission-mode auto --plugin-dir/);
} finally {
rmSync(root, { recursive: true, force: true });
}
});

test("installs from a public-style git source and is idempotent", () => {
const root = mkdtempSync(join(tmpdir(), "lmab-installer-"));
const source = join(root, "source-repo");
Expand Down