Static read-through audit of dpp-engine/cli, the odal CLI. No dead-end/no-op commands, no unsafe, no shell-injection risk, CSV export correctly neutralizes formula injection. Three verified findings.
1. Byte-index slicing on untrusted response bodies panics on multi-byte UTF-8
Location: src/core/passport/import.rs:86,177,200, src/core/passport/publish.rs:53,121
Issue: Error messages are built with &body[..body.len().min(200)] / .min(300) — str indexing panics if the cut point isn't a UTF-8 char boundary.
Failure scenario: Any vault/integrator error response containing a multi-byte character (accented names, curly quotes, non-Latin script in a field value) whose byte offset straddles 200/300 crashes the CLI mid-command instead of printing the truncated error.
2. Same byte-slicing bug in the shared render helper
Location: src/stateless/render.rs:20-26 (truncate())
Issue: Same unsafe byte-slice pattern, used on product_name (32-byte cutoff, user-entered vault data) and svc.url (38-byte cutoff). Note truncate_label in console/menu/passports.rs:405-412 already uses the correct chars().count()/chars().take() pattern elsewhere in the same crate.
Failure scenario: Any product name with a multi-byte character landing on the wrong byte offset panics odal passport list.
3. Credentials accepted as plain CLI arguments
Location: src/cli_args.rs:56-57 (Bootstrap { admin_pass }), 272-275 (KeyCommands::Use { secret })
Issue: Both accept a live credential (admin password / API-key secret) as a plain argument. On a multi-user host this lands in shell history and is readable by other local users via ps//proc/<pid>/cmdline for the process lifetime.
Failure scenario: admin_pass has an env-var fallback (ADMIN_PASSWORD), but the flag remains a viable, undocumented-as-risky path, and key use <secret> has no alternative at all.
Static read-through audit of
dpp-engine/cli, theodalCLI. No dead-end/no-op commands, no unsafe, no shell-injection risk, CSV export correctly neutralizes formula injection. Three verified findings.1. Byte-index slicing on untrusted response bodies panics on multi-byte UTF-8
Location:
src/core/passport/import.rs:86,177,200,src/core/passport/publish.rs:53,121Issue: Error messages are built with
&body[..body.len().min(200)]/.min(300)—strindexing panics if the cut point isn't a UTF-8 char boundary.Failure scenario: Any vault/integrator error response containing a multi-byte character (accented names, curly quotes, non-Latin script in a field value) whose byte offset straddles 200/300 crashes the CLI mid-command instead of printing the truncated error.
2. Same byte-slicing bug in the shared render helper
Location:
src/stateless/render.rs:20-26(truncate())Issue: Same unsafe byte-slice pattern, used on
product_name(32-byte cutoff, user-entered vault data) andsvc.url(38-byte cutoff). Notetruncate_labelinconsole/menu/passports.rs:405-412already uses the correctchars().count()/chars().take()pattern elsewhere in the same crate.Failure scenario: Any product name with a multi-byte character landing on the wrong byte offset panics
odal passport list.3. Credentials accepted as plain CLI arguments
Location:
src/cli_args.rs:56-57(Bootstrap { admin_pass }),272-275(KeyCommands::Use { secret })Issue: Both accept a live credential (admin password / API-key secret) as a plain argument. On a multi-user host this lands in shell history and is readable by other local users via
ps//proc/<pid>/cmdlinefor the process lifetime.Failure scenario:
admin_passhas an env-var fallback (ADMIN_PASSWORD), but the flag remains a viable, undocumented-as-risky path, andkey use <secret>has no alternative at all.