1-SEC contributors · Reviewed · Module: ai_containment

Agent URI Scheme Abuse: Reported Tool Payloads and Local Handlers

The agent-action handler inspects reported target and tool payload strings for URI candidates.

What 1-SEC checks

The agent-action handler inspects reported target and tool payload strings for URI candidates. It applies up to two query-unescape passes, parses bounded candidates and flags a fixed list of schemes including file, gopher, dict, expect, jar, local, nfs and smb. Matching input produces an unsafe-URI-handler alert. Ordinary HTTPS tool input does not match that scheme list; it can still trigger other policies or require independent destination controls.

Read the implementation: handleAgentAction

Required telemetry and context

Relevant input events: agent_action, tool_call, function_call. Use a trusted producer at the real application boundary.

  • agent_id
  • action
  • tool
  • target
  • tool arguments/content fields accepted by the action handler

Field names above describe relevant context, not a complete API request. Consult the current event contract for envelope and detail requirements. Preserve booleans, numbers, and strings as the receiving handler expects them. Agent-provided text cannot independently verify identity or authorization.

Deployment, prevention, and response

Keep OS and browser URI dispatch behind an executor policy that explicitly authorizes the action. Forward the original target and argument context from trusted instrumentation before dispatch, then have the executor refuse an unsafe decision. Use the inert raw/encoded URI and HTTPS fixtures to test the monitoring boundary. Resolve workspace files through scoped file APIs rather than passing untrusted file URIs to external handlers; review network destinations separately.

Record the source event, affected agent/host, actual target, policy decision, and response result. Review enforcement configuration separately from detection. A recommendation, selected action, dry-run record, and completed action are different outcomes.

Reproduce the source fixtures

From a checkout of the linked 1-SEC source revision, run the selected fixtures with the repository's Go toolchain. These commands run tests; they do not execute a real attack against your systems.

go test ./internal/modules/aicontainment -run '^(TestContainment_HandleEvent_UnsafeLocalURIHandler|TestContainment_HandleEvent_AllowsHTTPSAgentURI)$' -count=1

Actual handler fixtures cover raw and encoded unsafe URI examples and the absence of the unsafe-scheme alert for an HTTPS control. No URI is opened and no browser, network request or OS protocol handler is invoked.

TestContainment_HandleEvent_UnsafeLocalURIHandler

Full fixture and assertions — run in its original package with its helpers.

func TestContainment_HandleEvent_UnsafeLocalURIHandler(t *testing.T) {
	cp := makeCapturingPipeline()
	c := startedModuleWithPipeline(t, cp)
	defer c.Stop()

	ev := core.NewSecurityEvent("test", "tool_call", core.SeverityInfo, "fetch local file")
	ev.Details["agent_id"] = "agent-uri"
	ev.Details["action"] = "summarize"
	ev.Details["tool"] = "fetch_webpage"
	ev.Details["arguments"] = map[string]interface{}{
		"url": "file%3A%2F%2F%2Fworkspace%2Fconfig.json",
	}

	if err := c.HandleEvent(ev); err != nil {
		t.Fatalf("HandleEvent() error: %v", err)
	}
	if !cp.hasAlertType("agent_unsafe_uri_handler") {
		t.Fatalf("expected agent_unsafe_uri_handler alert; got %d alert(s)", cp.count())
	}
}
TestContainment_HandleEvent_AllowsHTTPSAgentURI

Full fixture and assertions — run in its original package with its helpers.

func TestContainment_HandleEvent_AllowsHTTPSAgentURI(t *testing.T) {
	cp := makeCapturingPipeline()
	c := startedModuleWithPipeline(t, cp)
	defer c.Stop()

	ev := core.NewSecurityEvent("test", "tool_call", core.SeverityInfo, "fetch documentation")
	ev.Details["agent_id"] = "agent-uri"
	ev.Details["action"] = "summarize"
	ev.Details["tool"] = "fetch_webpage"
	ev.Details["arguments"] = map[string]interface{}{"url": "https://go.dev/doc/"}

	if err := c.HandleEvent(ev); err != nil {
		t.Fatalf("HandleEvent() error: %v", err)
	}
	if cp.hasAlertType("agent_unsafe_uri_handler") {
		t.Fatal("did not expect agent_unsafe_uri_handler alert for HTTPS")
	}
}

Tuning, evaluation, and coverage limits

This is inspection of supplied strings, not an operating-system protocol registration policy or a browser sandbox. Unknown custom schemes, omitted payloads and representations beyond the implemented decoding path are not universally covered. At most sixteen URI candidates per decoded blob are examined. The alert title says blocked, but emitting it does not prevent an external application from invoking a local handler. An allowed HTTPS scheme does not establish a safe host, path, redirect chain or authenticated publisher.

Evaluate this behavior with representative authorized activity and a controlled known-positive case. Investigate the exact rule, inputs, and state before suppressing an alert. Do not assume a hard-coded heuristic is a configurable setting. Measure your own deployment; the source fixtures do not establish a benchmark, detection rate, compliance certification, or incident-prevention claim.

Protocol and format references

These references describe the underlying format or protocol. The implementation and fixtures above define the subset 1-SEC actually checks.

Related implemented controls

Implementation reviewed at source revision 4803febcb2bfe646bb74d1bf0f8f4e7fe8a880a6. Recheck the actual release and integration before deployment. Sources and corrections policy.