Skip to content

Secure Outbound Transport Threat Model

This document outlines the security posture, control-status mapping, and STRIDE-style threat matrix for the planned built-in outbound transport in MultiModel Dev OS.


1. Gateway Security & Outbound Transport Control Posture

Every security control across contract, validator, gate, executor, transport, and runtime layers is classified below using canonical status terms:

ControlLayerCurrent StatusDescription
URL Syntax ValidationValidator Layervalidator-enforcedValidates strict HTTPS scheme, parses valid URL format, and rejects invalid structures in validateProviderEndpoint().
Trusted Endpoint BindingGate Layergate-enforcedAsserts that execution_request.endpoint matches the provider's registered endpoint metadata before execution.
Hostname AllowlistingGate / Executor Layernot implementedHostname allowlisting per provider is planned; currently endpoints rely on URL syntax and endpoint binding.
DNS ResolutionTransport LayerplannedAsynchronous resolution of hostnames to IPv4/IPv6 addresses via node:dns/promises.
IP Classification (DNS-Level)Transport Layernot implementedPre-connection classification and fail-closed rejection of private, loopback, link-local, multicast, CGNAT, and reserved IP ranges.
Literal Private IP CheckValidator Layervalidator-enforcedString-based parsing rejects literal IP strings (e.g. 127.0.0.1, 10.0.0.1, 169.254.169.254); does not protect against domain-name DNS resolution to private IPs.
Connection-Time Address PinningTransport LayerplannedConnecting directly to pre-resolved and validated IP address using custom lookup in node:https or direct socket creation in node:net / node:tls.
TLS Certificate VerificationTransport Layernot implementedBuilt-in native transport with rejectUnauthorized: true and SNI preservation is planned for Sprint F2. Injected test transports handle TLS independently.
Redirect Handling (Contract)Gate / Validatorvalidator-enforcedValidator enforces follow_redirects: false; gate denies policy with follow_redirects: true.
Redirect Rejection (Transport)Transport LayerplannedBuilt-in transport strictly rejects HTTP 3xx responses without following redirect locations.
Request/Response Byte LimitsExecutor Layerexecutor-enforcedEnforces max_request_bytes and max_response_bytes at payload normalization and streaming levels.
Credential Header BoundaryTransport Layernot implementedConstructing Authorization: Bearer <secret> header exclusively inside transport using ResolvedCredential.withSecret() is planned for Sprint F2.
Timeout & CancellationExecutor / Runtimeexecutor-enforcedLifecycle timeouts (request_timeout_ms, response_timeout_ms) and AbortSignal propagation managed by executor.
Observability RedactionObservability Layerruntime-enforcedStrips prompts, completions, credentials, and sensitive headers from event metrics and trace logs.
Injected Transport TrustRuntime Layerruntime-enforcedGoverned execution in Sprint E1/E2 functions strictly via explicitly provided in-process transport implementations.

2. STRIDE Threat Matrix

The expanded STRIDE threat matrix documents key security assets, threat vectors, entry points, preconditions, impacts, mitigations, residual risks, responsible sprints, and current implementation status:

AssetAttackerEntry PointPreconditionImpactPrevention StrategyDetectionResidual RiskResponsible Sprint / TestCurrent Status
Local ServicesMalicious ConfigLocal Policy / EndpointConfig specifies private IP literal (e.g. 127.0.0.1)SSRF to local serviceString-based private IP rejection in validateProviderEndpoint()Validator error logsHostname resolving to loopback bypasses string checkSprint A (tests/unit/execution-security.test.js)validator-enforced
Local Services / Cloud MetadataUntrusted DNS / AttackerHostname ResolutionHostname resolves to private/loopback/link-local IPSSRF to internal network / metadata APIPre-connection IP range classification and fail-closed rejectionTransport audit logs & IP classifier errorsCompromised local DNS server prior to lookupSprint F1 (tests/unit/transport-destination-policy.test.js)planned
DNS ResolverNetwork MitMUpstream DNSAttacker tampers with DNS responseTraffic sent to malicious IPValidate all returned DNS IPs; pin socket; require TLS cert hostname matchTLS handshake failure on host mismatchMalicious server presents valid CA cert for target domainSprint F1 / F2 (tests/unit/transport-dns.test.js)planned
IP BoundariesMalicious DNS ServerHostname ResolutionDNS returns public IP first, then private IP on connectTOCTOU / DNS rebinding SSRFPin socket connection to pre-validated IP address via custom lookupPinned IP mismatch loggingAttacker controls public IP pointing to malicious serverSprint F1 / F2 (tests/unit/transport-pinning.test.js)planned
IP ClassificationMalicious DNS ServerHostname ResolutionDNS returns array containing both public and private IP addressesSSRF if unvalidated IP chosenRequire 100% of returned addresses to pass public IP classification; fail-closed on any private answerResolution failure logResolver returns single public IP that rebindsSprint F1 (tests/unit/transport-destination-policy.test.js)planned
Private NetworkUpstream ServerHTTP 3xx RedirectServer returns 302 Found pointing to internal IPSSRF via redirectHardcode follow_redirects: false; reject 3xx responses in transportResponse status loggingApplication logic interprets 3xx as successSprint F2 (tests/unit/transport-redirect.test.js)planned
API CredentialsNetwork MitMTLS HandshakeServer presents invalid or mismatched certCredential exfiltrationrejectUnauthorized: true; strict hostname SNI matching; no custom CAsTLS verification errorsCompromised root CA on OS hostSprint F2 (tests/unit/transport-tls.test.js)planned
API CredentialsCross-Provider AttackerExecution RequestReusing OpenAI key for AnthropicCredential leakage across providersScope credential references strictly per provider IDCredential resolver checksMisconfigured provider ID in requestSprint A / C (tests/unit/gateway-credential-resolution.test.js)contract-defined
Transport HeadersMalicious Header InjectorRequest InputHeader input contains \r\nHeader injection / request smuggling / token leakageStrict CR/LF rejection; allowlist limited to Authorization, Content-Type, Accept, User-AgentHeader validation errorsProcess memory inspection by local privileged userSprint A / F2 (tests/unit/transport-headers.test.js)validator-enforced (contract); planned (transport)
HTTP ParserMalicious UpstreamHTTP ResponseUpstream sends malformed HTTP headers/chunksResponse splitting / smugglingStrict standard-library HTTP parsing; validate response status and headersTransport parse errorsNode standard-library HTTP parser bugsSprint F2 (tests/unit/transport-response.test.js)planned
Gateway MemoryUpstream ServerResponse BodyServer sends compressed / bomb payloadOut-of-memory crashEnforce max_response_bytes; accept-encoding: identity; no transparent decompressionByte budget exceeded errorsMemory pressure prior to limit breachSprint A / F2 (tests/unit/transport-limits.test.js)executor-enforced (size); planned (transport encoding)
Gateway MemoryUpstream Server / UserRequest / Response PayloadMassive JSON payload submitted or returnedRAM exhaustionBounded max_request_bytes (<= 52MB) and max_response_bytes (<= 52MB)Payload limit errorsHigh memory usage near 52MB limitSprint A / B (tests/unit/gateway-execution.test.js)executor-enforced
Gateway SocketsMalicious UpstreamSSE StreamUpstream stream stalls without closingSocket / handle leakSeparate DNS, connect, TLS, header, idle, and total execution timeout timersTimeout execution logsTimers depend on Node event loop precisionSprint E2 / F2 (tests/integration/gateway-governed-runtime-stream.test.js)executor-enforced (executor timer); planned (transport phase timers)
Gateway SocketsMalicious UpstreamResponse Headers / BodyUpstream delays response headers or body chunksSlowloris resource exhaustionresponse_timeout_ms and idle response timeoutsTimeout execution logsSlowloris sending 1 byte every 29sSprint E1 / F2 (tests/unit/gateway-execution.test.js)executor-enforced
Gateway SocketsTransport ConnectionAbort SignalSocket ignores AbortSignal triggerUnkillable socket leakImmediate socket.destroy() on abort or timeoutCancellation logAsync socket teardown delaySprint E2 / F3 (tests/integration/gateway-governed-runtime-stream.test.js)executor-enforced (executor signal); planned (transport socket destruction)
Network EndpointsEnvironment / ProxyEnvironment VariablesAmbient HTTP_PROXY or HTTPS_PROXY setRequest redirected through untrusted proxyExplicitly ignore ambient proxy environment variables in built-in transportTransport initialization checkSystem-level OS network proxy redirectionSprint F2 (tests/unit/transport-proxy.test.js)planned
Provider ExecutionMalicious In-Process CodeTransport ParameterInjected transport contains malicious socket codeArbitrary execution / network accessInjected transport is trusted in-process code; validated via validateTransport()Transport contract validationCompromised node_modules or main thread codeSprint D (tests/unit/gateway-execution.test.js)executor-enforced
Credentials / PromptsObservability CollectorEvent / Trace LogsLogger records request/response bodies or auth headersSecret / prompt leakage in logsMandatory redaction pass; redact_prompts: true; authorization headers always strippedObservability audit assertionsMemory inspection of trace bufferSprint E1 / E2 (tests/integration/gateway-governed-runtime-stream.test.js)runtime-enforced
Connection PoolUpstream ConnectionHTTP Keep-Alive PoolReusing connection across different origins/providersCredential exfiltration / cross-origin context leakDisable connection reuse across distinct providers/origins in initial transportConnection pool auditPerformance overhead of fresh TCP/TLS handshakesSprint F2 (tests/unit/transport-pooling.test.js)planned
Trust StoreLocal AttackerLocal Workspace FileAttacker modifies .ai/registries/trusted-keys.yamlAcceptance of untrusted registry manifestsCryptographic Ed25519 signature checks; file access restrictedSignature validation errorsPrivileged local user overwriting trust storeSprint A (tests/unit/registry-trust-store.test.js)validator-enforced
Local HostnameLocal AttackerOS /etc/hosts FileAttacker maps provider domain to 127.0.0.1Local MitM / credential theftPre-connection IP range classification detects 127.0.0.1 after resolution and fails closedIP classification failure logAttacker maps domain to a public IP under their controlSprint F1 (tests/unit/transport-destination-policy.test.js)planned
IP BoundariesMalicious EndpointIPv6 Address FormatEndpoint uses IPv4-mapped IPv6 (e.g. ::ffff:127.0.0.1)SSRF bypass of IPv4 checksNormalize IPv4-mapped IPv6 addresses to IPv4 and classify against IPv4 rulesIP classification failure logObscure IPv6 translation mechanismsSprint F1 (tests/unit/transport-destination-policy.test.js)planned
IP BoundariesMalicious EndpointAlternate Numeric IPEndpoint uses octal (0177.0.0.1), hex (0x7f000001), or dword (2130706433)SSRF bypass of standard decimal parserReject non-canonical IPv4 representations; enforce standard 4-octet decimal dotted notationURL / IP validation errorsAmbiguous IP parser implementationsSprint F1 (tests/unit/transport-destination-policy.test.js)planned
Hostname ParserMalicious EndpointIDN / Unicode HostnameHomograph attack / Punycode confusionHostname spoofing / SNI mismatchReject non-ASCII raw host input in first implementation; enforce strict ASCII labelsEndpoint validation errorsFuture IDN expansionSprint F1 (tests/unit/transport-destination-policy.test.js)planned

3. Honest Security Boundaries & Non-Claims

  1. No Built-in Provider HTTP Transport: Current v4.3 Sprint E2 runtime executes governed requests only when an explicitly constructed transport object is injected. No built-in node:https transport exists in production code today.
  2. DNS-Level SSRF Protection: Current validator checks string syntax of endpoints (rejecting literal IP strings like 127.0.0.1), but does not perform DNS resolution or IP pinning prior to connection. DNS-level SSRF protection is planned for Sprint F1/F2.
  3. Physical Secret Zeroization: In JavaScript and Node.js runtime environments, physical memory zeroization after HTTP/TLS execution cannot be guaranteed due to internal V8 string copies and garbage collection behavior. Ephemeral credential objects utilize #secret private fields and .destroy() zeroing of internal references, but V8 engine memory strings may persist until garbage collected.
  4. Ambient Environment Proxy Isolation: Built-in transport will explicitly ignore ambient process environment variables (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY) to prevent unintended request redirection.

Released under the MIT License.