Reject invalid marketplace names on add

This commit is contained in:
xli-oai
2026-04-08 21:55:13 -07:00
parent bd32fb42de
commit 972d3a5495
3 changed files with 55 additions and 8 deletions

View File

@@ -7,6 +7,7 @@ use codex_core::plugins::OPENAI_CURATED_MARKETPLACE_NAME;
use codex_core::plugins::marketplace_install_root;
use codex_core::plugins::record_installed_marketplace_root;
use codex_core::plugins::validate_marketplace_root;
use codex_core::plugins::validate_plugin_segment;
use codex_utils_cli::CliConfigOverrides;
use std::fs;
use std::path::Path;
@@ -154,7 +155,7 @@ async fn run_add(args: AddMarketplaceArgs) -> Result<()> {
}
}
let marketplace_name = validate_marketplace_root(&staged_root)
let marketplace_name = validate_marketplace_source_root(&staged_root)
.with_context(|| format!("failed to validate marketplace from {}", source.display()))?;
if marketplace_name == OPENAI_CURATED_MARKETPLACE_NAME {
bail!(
@@ -185,6 +186,12 @@ async fn run_add(args: AddMarketplaceArgs) -> Result<()> {
Ok(())
}
fn validate_marketplace_source_root(root: &Path) -> Result<String> {
let marketplace_name = validate_marketplace_root(root)?;
validate_plugin_segment(&marketplace_name, "marketplace name").map_err(anyhow::Error::msg)?;
Ok(marketplace_name)
}
fn parse_marketplace_source(
source: &str,
explicit_ref: Option<String>,

View File

@@ -13,22 +13,32 @@ fn codex_command(codex_home: &Path) -> Result<assert_cmd::Command> {
}
fn write_marketplace_source(source: &Path, marker: &str) -> Result<()> {
write_marketplace_source_with_name(source, "debug", marker)
}
fn write_marketplace_source_with_name(
source: &Path,
marketplace_name: &str,
marker: &str,
) -> Result<()> {
std::fs::create_dir_all(source.join(".agents/plugins"))?;
std::fs::create_dir_all(source.join("plugins/sample/.codex-plugin"))?;
std::fs::write(
source.join(".agents/plugins/marketplace.json"),
r#"{
"name": "debug",
format!(
r#"{{
"name": "{marketplace_name}",
"plugins": [
{
{{
"name": "sample",
"source": {
"source": {{
"source": "local",
"path": "./plugins/sample"
}
}
}}
}}
]
}"#,
}}"#
),
)?;
std::fs::write(
source.join("plugins/sample/.codex-plugin/plugin.json"),
@@ -65,6 +75,35 @@ async fn marketplace_add_local_directory_installs_valid_marketplace_root() -> Re
Ok(())
}
#[tokio::test]
async fn marketplace_add_rejects_invalid_marketplace_name() -> Result<()> {
let codex_home = TempDir::new()?;
let source = TempDir::new()?;
write_marketplace_source_with_name(source.path(), "debug.market", "invalid marketplace")?;
codex_command(codex_home.path())?
.args(["marketplace", "add", source.path().to_str().unwrap()])
.assert()
.failure()
.stderr(contains(
"invalid marketplace name: only ASCII letters, digits, `_`, and `-` are allowed",
));
assert!(
!marketplace_install_root(codex_home.path())
.join("debug.market")
.exists()
);
assert!(
!codex_home
.path()
.join(".tmp/known_marketplaces.json")
.exists()
);
Ok(())
}
#[tokio::test]
async fn marketplace_add_same_source_is_idempotent() -> Result<()> {
let codex_home = TempDir::new()?;

View File

@@ -20,6 +20,7 @@ pub use codex_plugin::PluginCapabilitySummary;
pub use codex_plugin::PluginId;
pub use codex_plugin::PluginIdError;
pub use codex_plugin::PluginTelemetryMetadata;
pub use codex_plugin::validate_plugin_segment;
pub type LoadedPlugin = codex_plugin::LoadedPlugin<McpServerConfig>;
pub type PluginLoadOutcome = codex_plugin::PluginLoadOutcome<McpServerConfig>;