Enforce Agent Plugin runtime boundaries (#37027)

## What changed

- Track Agent Plugin manifests through plugin, skill, and MCP loading so their capabilities use format-specific behavior without changing legacy plugins.
- Discover only direct-child skills, exclude app and hook capabilities, isolate MCP data, and reject MCP configuration files that are non-regular or resolve outside the plugin root.
- Bound model-visible skill instructions, plugin instructions, MCP descriptions, schemas, individual tools, and the aggregate Agent Plugin MCP tool set.
- Stop MCP and OAuth redirects when Agent Plugins send configured or authorization headers, while retaining existing redirect behavior for legacy MCP servers.

## Testing

- Add coverage for capability filtering, skill discovery, isolated MCP data and reserved-path expansion, unsafe MCP configuration files, context limits, and redirect handling.

GitOrigin-RevId: c9af66b051269f3226628ca280a58d32c808c38f
This commit is contained in:
jacobzhou-oai authored and copyberry committed 2026-08-05 04:54:33 +00:00
1 parent f21dc46388
commit 56b82e676c
63 files changed
+1830 -106

No files matched your search

@@ -1,11 +1,15 @@
use std::io::ErrorKind;
use codex_exec_server::HttpRedirectPolicy;
use http::HeaderMap;
use http::HeaderValue;
use http::header::AUTHORIZATION;
use pretty_assertions::assert_eq;
use super::HttpHeader;
use super::SseEventSizeLimit;
use super::StreamableHttpRedirectMode;
use super::mcp_redirect_policy;
use super::protocol_headers;
#[test]
@@ -25,6 +29,64 @@ fn protocol_headers_preserve_utf8_values() {
);
}
#[test]
fn legacy_configured_headers_follow_redirects() {
assert_eq!(
mcp_redirect_policy(
StreamableHttpRedirectMode::Legacy,
&HeaderMap::new(),
/*has_configured_headers*/ true,
),
HttpRedirectPolicy::Follow
);
}
#[test]
fn agent_plugin_configured_headers_stop_redirects() {
assert_eq!(
mcp_redirect_policy(
StreamableHttpRedirectMode::AgentPluginV1,
&HeaderMap::new(),
/*has_configured_headers*/ true,
),
HttpRedirectPolicy::Stop
);
}
#[test]
fn requests_without_sensitive_headers_follow_redirects() {
assert_eq!(
mcp_redirect_policy(
StreamableHttpRedirectMode::AgentPluginV1,
&HeaderMap::new(),
/*has_configured_headers*/ false,
),
HttpRedirectPolicy::Follow
);
}
#[test]
fn authorization_redirects_depend_on_mode() {
let mut headers = HeaderMap::new();
headers.insert(AUTHORIZATION, HeaderValue::from_static("Bearer secret"));
assert_eq!(
mcp_redirect_policy(
StreamableHttpRedirectMode::Legacy,
&headers,
/*has_configured_headers*/ false,
),
HttpRedirectPolicy::Follow
);
assert_eq!(
mcp_redirect_policy(
StreamableHttpRedirectMode::AgentPluginV1,
&headers,
/*has_configured_headers*/ false,
),
HttpRedirectPolicy::Stop
);
}
#[test]
fn lf_terminators_reset_the_event_limit() {
let mut limit = SseEventSizeLimit::new(Some(8));