mirror of
https://github.com/openai/codex.git
synced 2026-10-23 18:08:45 +00:00
Reject unknown MCP keys in partial layers
This commit is contained in:
@@ -493,6 +493,49 @@ enabled = false
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn write_value_rejects_unknown_mcp_field_hidden_by_cloud_config() -> Result<()> {
|
||||
let tmp = tempdir().expect("tempdir");
|
||||
let config_path = tmp.path().join(CONFIG_TOML_FILE);
|
||||
std::fs::write(&config_path, "")?;
|
||||
let service = ConfigManager::new_for_tests(
|
||||
tmp.path().to_path_buf(),
|
||||
vec![],
|
||||
LoaderOverrides::without_managed_config_for_tests(),
|
||||
CloudConfigBundleFixture::loader_with_enterprise_config(
|
||||
r#"[mcp_servers.docs]
|
||||
command = "cloud-docs-server"
|
||||
enabled = false
|
||||
"#,
|
||||
),
|
||||
);
|
||||
|
||||
let error = service
|
||||
.write_value(ConfigValueWriteParams {
|
||||
file_path: Some(config_path.display().to_string()),
|
||||
key_path: "mcp_servers.docs.typo".to_string(),
|
||||
value: serde_json::json!(true),
|
||||
merge_strategy: MergeStrategy::Replace,
|
||||
expected_version: None,
|
||||
})
|
||||
.await
|
||||
.expect_err("the cloud transport must not hide an unknown user-layer field");
|
||||
|
||||
assert_eq!(
|
||||
error.write_error_code(),
|
||||
Some(ConfigWriteErrorCode::ConfigValidationError)
|
||||
);
|
||||
assert!(
|
||||
error
|
||||
.to_string()
|
||||
.contains("unknown configuration field `mcp_servers.docs.typo`"),
|
||||
"{error}"
|
||||
);
|
||||
assert_eq!(std::fs::read_to_string(config_path)?, "");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn read_includes_origins_and_layers() {
|
||||
let tmp = tempdir().expect("tempdir");
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use crate::config_toml::ConfigToml;
|
||||
use crate::mcp_types::RawMcpServerConfig;
|
||||
use crate::strict_config::ignored_toml_value_field;
|
||||
use codex_utils_absolute_path::AbsolutePathBufGuard;
|
||||
use serde::Deserialize;
|
||||
use serde::de::Error as _;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use toml::Value as TomlValue;
|
||||
@@ -17,6 +19,13 @@ impl ParsedConfigTomlLayer {
|
||||
pub fn parse(raw: TomlValue, base_dir: &Path) -> Result<Self, toml::de::Error> {
|
||||
let parts = split_config_toml_layer(raw.clone());
|
||||
let _guard = AbsolutePathBufGuard::new(base_dir);
|
||||
if let Some(ignored_field) =
|
||||
ignored_toml_value_field::<ConfigTomlComposableSections>(parts.composable.clone())
|
||||
{
|
||||
return Err(toml::de::Error::custom(format!(
|
||||
"unknown configuration field `{ignored_field}`"
|
||||
)));
|
||||
}
|
||||
let _: ConfigTomlComposableSections = parts.composable.try_into()?;
|
||||
let self_contained_config = parts.self_contained.try_into()?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user