Summary

  • CGI/1.1 described a common request-and-response handoff between an HTTP server and a script, even as some details remained system- or implementation-defined.
  • RFC 3875 placed TLS between the client and server: the server was authenticated to the client, while the script received no built-in proof of who invoked it or an integrity-protected CGI message.

The connection is secure. The application is not necessarily on the other end of it.

That distinction is the quiet boundary in RFC 3875, the 2004 Common Gateway Interface (CGI) Version 1.1 specification. A browser can establish TLS with a web server. The server can then pass request data to a CGI program. But the security relationship the RFC describes does not travel intact across that second handoff. The server is the network peer; the script is an application process behind it.

CGI had been doing useful work long before RFC 3875 appeared. An HTTP server could act as a gateway to a database or another existing information system, while a script produced a response from the request. The W3C’s historical CGI page calls the interface an agreement among server implementers for integrating gateway scripts and programs. It records a 1995 attempt to update CGI 1.1 and an effort reactivated in November 1997 to turn a de facto interface into an Informational RFC. The eventual RFC was published in October 2004 through the Independent Submission Stream.

The long interval matters less as a standards-process curiosity than as evidence of what the document was trying to capture. CGI was already a practical convention. RFC 3875 did not invent dynamic web applications; it wrote down a portable contract around a request that had to cross from a network-facing server into an application program.

The contract names request “meta-variables” such as REQUEST_METHOD, QUERY_STRING, CONTENT_LENGTH, PATH_INFO and REMOTE_ADDR. It defines how a script returns headers and a body, including document and redirect responses. This gives programs written for different servers a common vocabulary. It also locates responsibilities: the server manages the client connection, data transfer and network protocol; the script performs application work such as data access and document processing.

The division is not a transfer of the server’s obligations. RFC 3875 says that even if a script fails to conform, the server remains responsible to the client for conforming to the network protocol. It also requires a server applying authentication not to execute the script until the request has passed the defined access controls. The server is not simply a transparent pipe that can blame its child process for a bad response or skipped gate.

Then section 9.4 narrows the trust boundary. For a TLS client connection, the security model applies between client and server, not between client and script. The server is authenticated to the client. The specification gives the script no mechanism to authenticate the server that invoked it, and it does not enforce integrity on the CGI request and response messages.

That is not a claim that the script must be untrusted, or that an operator cannot protect the local process boundary. A server can use operating-system permissions, a private channel or other local controls. The narrower point is that TLS at the HTTP edge does not, by itself, authenticate the downstream script as the same endpoint. A script receiving HTTPS=on or a user name in its environment has received values; the CGI interface has not supplied a cryptographic proof binding those values to an authenticated client session.

The architecture was intentionally broader than one process model. RFC 3875 describes a child process running under the server’s user and group as the most common implementation, but also acknowledges scripts linked into the server. It marks behavior that can vary across systems as “system-defined” and behavior that can vary by implementation as “implementation-defined.” The common interface could travel farther than any one server’s execution machinery, but that portability had limits.

Apache’s mod_cgi documentation is a useful implementation example, not a census of the web. It shows one server family selecting scripts through handlers or ScriptAlias and returning their output to clients. That machinery illustrates the handoff; it does not change the RFC’s claim about where TLS terminates or establish how all servers were configured.

CGI’s historical achievement was a shared boundary, not a shared process or end-to-end security channel. The server and script could cooperate through a named interface, while remaining distinct principals with different responsibilities. Reading the RFC that way avoids a common category error: a protected browser-to-server request is not automatically a protected browser-to-application relationship. RFC 3875 made the split explicit; it did not erase it.

Sources