Kcgi – minimal CGI and FastCGI library for C/C++

Hacker News Top Tools

Summary

kcgi 是一个面向 C/C++ Web 应用的极简、安全且易于审计的开源 CGI 与 FastCGI 库,最新发布 1.0.1 版本,修复了 macOS 共享库命名问题。它支持自动压缩、HTTP 输入处理与验证、认证、沙箱化处理不可信输入等特性。

No content available
Original Article
View Cached Full Text

Cached at: 10/14/26, 07:01 AM

# kcgi: minimal CGI and FastCGI library for C/C++ Source: [https://kristaps.bsd.lv/kcgi/](https://kristaps.bsd.lv/kcgi/) kcgiis an[open source](http://opensource.org/licenses/ISC)CGI and FastCGI library for C/C\+\+ web applications\. It is minimal, secure, and auditable\. To start,[install](https://kristaps.bsd.lv/kcgi/#install)the library\. Then read the[deployment](https://kristaps.bsd.lv/kcgi/#deploying)and[usage](https://kristaps.bsd.lv/kcgi/#usage)guides\. The following echoesHello, World\!as an HTTP response to a CGI request\.For fuller examples, see[sample\.c](https://kristaps.bsd.lv/kcgi/sample.c.html)\(C and CGI\),[samplepp\.cc](https://kristaps.bsd.lv/kcgi/samplepp.cc.html)\(C\+\+ and CGI\),[sample\-fcgi\.c](https://kristaps.bsd.lv/kcgi/sample-fcgi.c.html)\(C and FastCGI\), or jump to the[Documentation](https://kristaps.bsd.lv/kcgi/#usage)section\. *kcgi*supports many features: auto\-compression, handling of all HTTP input operations \(query strings, cookies, page bodies, multipart\) with validation, authentication, configurable output caching, request debugging, formatted writers \(JSON, XML, etc\.\) and so on\. Its strongest differentiating feature is using sandboxing and process separation for handling the untrusted input path\. ## current release - Version1\.0\.1:2025\-11\-17 Hot\-fix 1\.0\.0 with proper naming of Mac OS X shared libraries, which use a different convention of version suffix than other Unix\-like systems\. \([release archive](https://kristaps.bsd.lv/kcgi/archive.html)\) ## installation First, check ifkcgiisn't already packaged for your system, such as with`pkg\_add kcgi`\(OpenBSD\),`pkg install kcgi`\(FreeBSD\),`brew install kcgi`\(brew\),`pacman \-S kcgi`\(Arch Linux\), and so on\. If so, install using that system\. If not,kcgihas been built and run on GNU/[Linux](https://www.linux.org/)\(musl and glibc\),[OpenBSD](https://www.openbsd.org/),[NetBSD](https://www.netbsd.org/),[FreeBSD](https://www.freebsd.org/)\),[Solaris](https://www.oracle.com/solaris/solaris11),[OmniOS](https://omniosce.org/), and[Mac OS X](https://www.apple.com/osx)\(only Mojave and newer\!\) on i386, amd64, powerpc, arm64, and sparc64\. Download[kcgi\.tgz](https://kristaps.bsd.lv/kcgi/snapshots/kcgi.tgz)and verify the archive with[kcgi\.tgz\.sha512](https://kristaps.bsd.lv/kcgi/snapshots/kcgi.tgz.sha512)\. To run bleeding\-edge code between releases, the repository is on[GitHub](https://github.com/kristapsdz/kcgi)\. In both cases, build and install instructions may be found on the repository page\. The only hard build\-time dependency is BSD make \(`bmake`on Linux\) and[zlib](https://www.zlib.net/)\. If you're running the regression tests \(see[Testing](https://kristaps.bsd.lv/kcgi/#testing)\), you'll also need[libcurl](https://curl.haxx.se/libcurl/)\. ## deployment To usekcgi, you'll need a web server capable of running CGI or FastCGI\.[Apache](https://httpd.apache.org/),[nginx](https://nginx.org/), and OpenBSD's[httpd\(8\)](https://man.openbsd.org/httpd.8)have all been used extensively, with the latter two natively over FastCGI and via the`slowcgi`wrapper\. To compilekcgiapplications, use the package configuration\. Linking is similarly normative\. ``` % cc `pkg-config --cflags kcgi` -c yourprog.c % cc yourprog.o `pkg-config --libs kcgi` ``` Well\-deployed web servers, such as the default[OpenBSD](https://www.openbsd.org/)server, by default are deployed within a[chroot\(2\)](https://man.openbsd.org/chroot.2)\. If this is the case, you'll need to statically link your binary \(or pull all shared libraries into the shadow root\)\. ``` % cc -static yourprog.o `pkg-config --static --libs kcgi` ``` FastCGI applications may either be started directly by the web server \(which is popular with[Apache](https://httpd.apache.org/)\) orexternallygiven a socket and[kfcgi\(8\)](https://kristaps.bsd.lv/kcgi/kfcgi.8.html)\(this method is normative for OpenBSD's[httpd\(8\)](https://man.openbsd.org/httpd.8)and suggested for the security precautions taken by the wrapper\)\. ## documentation Thekcgimanpages, starting with[kcgi\(3\)](https://kristaps.bsd.lv/kcgi/kcgi.3.html), are the canonical source of documentation\. The following is a list of all manpages: - [kcgi\.3](https://kristaps.bsd.lv/kcgi/kcgi.3.html) - [kcgi\_buf\_printf\.3](https://kristaps.bsd.lv/kcgi/kcgi_buf_printf.3.html) - [kcgi\_buf\_putc\.3](https://kristaps.bsd.lv/kcgi/kcgi_buf_putc.3.html) - [kcgi\_buf\_puts\.3](https://kristaps.bsd.lv/kcgi/kcgi_buf_puts.3.html) - [kcgi\_buf\_write\.3](https://kristaps.bsd.lv/kcgi/kcgi_buf_write.3.html) - [kcgi\_strerror\.3](https://kristaps.bsd.lv/kcgi/kcgi_strerror.3.html) - [kcgi\_writer\_disable\.3](https://kristaps.bsd.lv/kcgi/kcgi_writer_disable.3.html) - [kcgi\_writer\_free\.3](https://kristaps.bsd.lv/kcgi/kcgi_writer_free.3.html) - [kcgi\_writer\_get\.3](https://kristaps.bsd.lv/kcgi/kcgi_writer_get.3.html) - [kcgi\_writer\_putc\.3](https://kristaps.bsd.lv/kcgi/kcgi_writer_putc.3.html) - [kcgi\_writer\_puts\.3](https://kristaps.bsd.lv/kcgi/kcgi_writer_puts.3.html) - [kcgi\_writer\_write\.3](https://kristaps.bsd.lv/kcgi/kcgi_writer_write.3.html) - [kcgihtml\.3](https://kristaps.bsd.lv/kcgi/kcgihtml.3.html) - [kcgijson\.3](https://kristaps.bsd.lv/kcgi/kcgijson.3.html) - [kcgiregress\.3](https://kristaps.bsd.lv/kcgi/kcgiregress.3.html) - [kcgixml\.3](https://kristaps.bsd.lv/kcgi/kcgixml.3.html) - [kfcgi\.8](https://kristaps.bsd.lv/kcgi/kfcgi.8.html) - [khtml\_attr\.3](https://kristaps.bsd.lv/kcgi/khtml_attr.3.html) - [khtml\_close\.3](https://kristaps.bsd.lv/kcgi/khtml_close.3.html) - [khtml\_closeelem\.3](https://kristaps.bsd.lv/kcgi/khtml_closeelem.3.html) - [khtml\_closeto\.3](https://kristaps.bsd.lv/kcgi/khtml_closeto.3.html) - [khtml\_double\.3](https://kristaps.bsd.lv/kcgi/khtml_double.3.html) - [khtml\_elem\.3](https://kristaps.bsd.lv/kcgi/khtml_elem.3.html) - [khtml\_elemat\.3](https://kristaps.bsd.lv/kcgi/khtml_elemat.3.html) - [khtml\_entity\.3](https://kristaps.bsd.lv/kcgi/khtml_entity.3.html) - [khtml\_int\.3](https://kristaps.bsd.lv/kcgi/khtml_int.3.html) - [khtml\_ncr\.3](https://kristaps.bsd.lv/kcgi/khtml_ncr.3.html) - [khtml\_open\.3](https://kristaps.bsd.lv/kcgi/khtml_open.3.html) - [khtml\_printf\.3](https://kristaps.bsd.lv/kcgi/khtml_printf.3.html) - [khtml\_putc\.3](https://kristaps.bsd.lv/kcgi/khtml_putc.3.html) - [khtml\_puts\.3](https://kristaps.bsd.lv/kcgi/khtml_puts.3.html) - [khtml\_write\.3](https://kristaps.bsd.lv/kcgi/khtml_write.3.html) - [khttp\_body\.3](https://kristaps.bsd.lv/kcgi/khttp_body.3.html) - [khttp\_datetime2epoch\.3](https://kristaps.bsd.lv/kcgi/khttp_datetime2epoch.3.html) - [khttp\_epoch2datetime\.3](https://kristaps.bsd.lv/kcgi/khttp_epoch2datetime.3.html) - [khttp\_epoch2str\.3](https://kristaps.bsd.lv/kcgi/khttp_epoch2str.3.html) - [khttp\_epoch2tms\.3](https://kristaps.bsd.lv/kcgi/khttp_epoch2tms.3.html) - [khttp\_fcgi\_free\.3](https://kristaps.bsd.lv/kcgi/khttp_fcgi_free.3.html) - [khttp\_fcgi\_getfd\.3](https://kristaps.bsd.lv/kcgi/khttp_fcgi_getfd.3.html) - [khttp\_fcgi\_init\.3](https://kristaps.bsd.lv/kcgi/khttp_fcgi_init.3.html) - [khttp\_fcgi\_parse\.3](https://kristaps.bsd.lv/kcgi/khttp_fcgi_parse.3.html) - [khttp\_fcgi\_test\.3](https://kristaps.bsd.lv/kcgi/khttp_fcgi_test.3.html) - [khttp\_free\.3](https://kristaps.bsd.lv/kcgi/khttp_free.3.html) - [khttp\_head\.3](https://kristaps.bsd.lv/kcgi/khttp_head.3.html) - [khttp\_parse\.3](https://kristaps.bsd.lv/kcgi/khttp_parse.3.html) - [khttp\_printf\.3](https://kristaps.bsd.lv/kcgi/khttp_printf.3.html) - [khttp\_putc\.3](https://kristaps.bsd.lv/kcgi/khttp_putc.3.html) - [khttp\_puts\.3](https://kristaps.bsd.lv/kcgi/khttp_puts.3.html) - [khttp\_template\.3](https://kristaps.bsd.lv/kcgi/khttp_template.3.html) - [khttp\_templatex\.3](https://kristaps.bsd.lv/kcgi/khttp_templatex.3.html) - [khttp\_urlabs\.3](https://kristaps.bsd.lv/kcgi/khttp_urlabs.3.html) - [khttp\_urldecode\.3](https://kristaps.bsd.lv/kcgi/khttp_urldecode.3.html) - [khttp\_urlencode\.3](https://kristaps.bsd.lv/kcgi/khttp_urlencode.3.html) - [khttp\_urlpart\.3](https://kristaps.bsd.lv/kcgi/khttp_urlpart.3.html) - [khttp\_write\.3](https://kristaps.bsd.lv/kcgi/khttp_write.3.html) - [khttpbasic\_validate\.3](https://kristaps.bsd.lv/kcgi/khttpbasic_validate.3.html) - [khttpdigest\_validate\.3](https://kristaps.bsd.lv/kcgi/khttpdigest_validate.3.html) - [kjson\_array\_close\.3](https://kristaps.bsd.lv/kcgi/kjson_array_close.3.html) - [kjson\_array\_open\.3](https://kristaps.bsd.lv/kcgi/kjson_array_open.3.html) - [kjson\_close\.3](https://kristaps.bsd.lv/kcgi/kjson_close.3.html) - [kjson\_obj\_close\.3](https://kristaps.bsd.lv/kcgi/kjson_obj_close.3.html) - [kjson\_obj\_open\.3](https://kristaps.bsd.lv/kcgi/kjson_obj_open.3.html) - [kjson\_open\.3](https://kristaps.bsd.lv/kcgi/kjson_open.3.html) - [kjson\_putbool\.3](https://kristaps.bsd.lv/kcgi/kjson_putbool.3.html) - [kjson\_putdouble\.3](https://kristaps.bsd.lv/kcgi/kjson_putdouble.3.html) - [kjson\_putint\.3](https://kristaps.bsd.lv/kcgi/kjson_putint.3.html) - [kjson\_putnull\.3](https://kristaps.bsd.lv/kcgi/kjson_putnull.3.html) - [kjson\_putstring\.3](https://kristaps.bsd.lv/kcgi/kjson_putstring.3.html) - [kjson\_string\_close\.3](https://kristaps.bsd.lv/kcgi/kjson_string_close.3.html) - [kjson\_string\_open\.3](https://kristaps.bsd.lv/kcgi/kjson_string_open.3.html) - [kjson\_string\_write\.3](https://kristaps.bsd.lv/kcgi/kjson_string_write.3.html) - [kmalloc\.3](https://kristaps.bsd.lv/kcgi/kmalloc.3.html) - [kutil\_invalidate\.3](https://kristaps.bsd.lv/kcgi/kutil_invalidate.3.html) - [kutil\_log\.3](https://kristaps.bsd.lv/kcgi/kutil_log.3.html) - [kutil\_openlog\.3](https://kristaps.bsd.lv/kcgi/kutil_openlog.3.html) - [kvalid\_string\.3](https://kristaps.bsd.lv/kcgi/kvalid_string.3.html) - [kxml\_close\.3](https://kristaps.bsd.lv/kcgi/kxml_close.3.html) - [kxml\_open\.3](https://kristaps.bsd.lv/kcgi/kxml_open.3.html) - [kxml\_pop\.3](https://kristaps.bsd.lv/kcgi/kxml_pop.3.html) - [kxml\_popall\.3](https://kristaps.bsd.lv/kcgi/kxml_popall.3.html) - [kxml\_prologue\.3](https://kristaps.bsd.lv/kcgi/kxml_prologue.3.html) - [kxml\_push\.3](https://kristaps.bsd.lv/kcgi/kxml_push.3.html) - [kxml\_pushnull\.3](https://kristaps.bsd.lv/kcgi/kxml_pushnull.3.html) - [kxml\_putc\.3](https://kristaps.bsd.lv/kcgi/kxml_putc.3.html) - [kxml\_puts\.3](https://kristaps.bsd.lv/kcgi/kxml_puts.3.html) - [kxml\_write\.3](https://kristaps.bsd.lv/kcgi/kxml_write.3.html) Alternatively, the following are introductory materials to the system: - ### [Getting Started with CGI in C](https://kristaps.bsd.lv/kcgi/tutorial0.html) This tutorial describes a typical CGI example usingkcgi\. In it, I'll process HTML form input with two named fields,`string`\(a non\-empty, unbounded string\) and`integer`, a signed 64\-bit integer\. I'll then output the input within a simple HTML page\. The tutorial will be laid out in code snippets, which I'll put together at the end\. I'll then follow with compilation instructions\. - ### [Getting and Setting CGI Cookies in C](https://kristaps.bsd.lv/kcgi/tutorial1.html) Cookies are an integral part of any web application\. In this tutorial, I'll describe how to use the HTTP header functionality inkcgito set, recognise, and store cookies\. - ### [FastCGI Deployments](https://kristaps.bsd.lv/kcgi/tutorial2.html) FastCGI allows for much higher throughput by running web applications as daemons\. In this tutorial, I'll describe how to deploy a simple FastCGI application using[kfcgi\(8\)](https://kristaps.bsd.lv/kcgi/kfcgi.8.html)\. - ### [Custom Validation](https://kristaps.bsd.lv/kcgi/tutorial3.html) Applications often need to validate more then doubles, integers, or strings included in[kvalid\_string\(3\)](https://kristaps.bsd.lv/kcgi/kvalid_string.3.html)\. In this tutorial, I'll provide some examples on how to override the validation function\. - ### [Using Pages](https://kristaps.bsd.lv/kcgi/tutorial4.html) The tutorial gives an overview of the basic path handling provided bykcgi, and then shows and discusses relevant code snippets\. - ### [CGI for C\+\+ applications](https://kristaps.bsd.lv/kcgi/tutorial5.html) kcgisupports C\+\+ callers just as easily as C\. In this brief tutorial I'll take you through compiling a C\+\+ application that uses thekcgilibrary\. - ### [Best practises for pledge\(2\) security](https://kristaps.bsd.lv/kcgi/tutorial6.html) Let's set the record straight for securingkcgiCGI and FastCGI applications with[pledge\(2\)](https://man.openbsd.org/pledge.2)\. This is focussed on secure[OpenBSD](https://www.openbsd.org/)deployments\. - ### [CORS and kcgi](https://kristaps.bsd.lv/kcgi/tutorial7.html) This article isn't about CORS \(cross\-origin resource sharing\) but rather the enumerations and functions available in[kcgi\(3\)](https://kristaps.bsd.lv/kcgi/kcgi.3.html)to handle CORS requests\. In addition to these resources, the following conference sessions have referencedkcgi\. - Dzonsons, Kristaps\.*Role\-based Access Control in BCHS Web Applications*\. Proceedings of[AsiaBSDCon](https://2018.asiabsdcon.org/), Tokyo, Japan, March 2018\. \([Slides](https://kristaps.bsd.lv/absdcon2018),[video](https://www.youtube.com/watch?v=FzF9e4jrnJ4)\.\)[paper](https://kristaps.bsd.lv/absdcon2018/paper.pdf)\.\) - Dzonsons, Kristaps\.*Secure BSD Web Applications in C: Practical Strategies*\. Proceedings of[AsiaBSDCon](https://2017.asiabsdcon.org/), Tokyo, Japan, March 2017\. \([Slides](https://kristaps.bsd.lv/absdcon2017)\.\) - Dzonsons, Kristaps\.*Secure BSD Web Application Development in C*\. Proceedings of[AsiaBSDCon](https://2016.asiabsdcon.org/), Tokyo, Japan, March 2016\. \([Slides](https://kristaps.bsd.lv/absdcon2016)\.\) - Dzonsons, Kristaps\.*kcgi: securing CGI applications in C*\. Proceedings of[AsiaBSDCon](https://2015.asiabsdcon.org/), Tokyo, Japan, March 2015\. \([Slides](https://kristaps.bsd.lv/absdcon2015/talk.pdf),[paper](https://kristaps.bsd.lv/absdcon2015/paper.pdf)\.\) And the following relate to extending standards: - Dzonsons, Kristaps\.[FastCGI Extensions for Management Control](https://kristaps.bsd.lv/kcgi/extending01.html)\. March 2016\. ## implementation details The bulk ofkcgi's CGI handling lies in[khttp\_parse\(3\)](https://kristaps.bsd.lv/kcgi/khttp_parse.3.html), which fully parses the HTTP request\. Application developers must invoke this function before all others\. For FastCGI, this function is split between[khttp\_fcgi\_init\(3\)](https://kristaps.bsd.lv/kcgi/khttp_fcgi_init.3.html), which initialises context; and[khttp\_fcgi\_parse\(3\)](https://kristaps.bsd.lv/kcgi/khttp_fcgi_parse.3.html), which receives new parsed requests\. In either case, requests must be freed by[khttp\_free\(3\)](https://kristaps.bsd.lv/kcgi/khttp_free.3.html)\. All functions isolate the parsing and validation of untrusted network data within a*sandboxed*child process\. Sandboxes limit the environment available to a process, so exploitable errors in the parsing process \(or validation with third\-party libraries\) cannot touch the system environment\. This parsed data is returned to the parent process over a socket\. In the following, the*HTTP parser*and*input validator*manage a single HTTP request, while*connection delegator*accepts new HTTP requests and passes them along\. ![Implementation Details](https://kristaps.bsd.lv/kcgi/figure1.svg)![Implementation Details](https://kristaps.bsd.lv/kcgi/figure4.svg)This method of sandboxing the untrusted parsing process follows[OpenSSH](http://www.openssh.org/), and requires special handling for each operating system: [seccomp\(2\)](http://man7.org/linux/man-pages/man2/seccomp.2.html)\(Linux\)This requires a seccomp\-enabled Linux kernel and a recognised hardware architecture\. It is supplemented by`setrlimit\(2\)`limiting\.[pledge\(2\)](https://man.openbsd.org/pledge.2)\([OpenBSD](https://www.openbsd.org/)\)This will only work on OpenBSD \>5\.8\.[sandbox\_init\(3\)](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/sandbox_init.3.html)\([Apple OSX](https://www.apple.com/osx/)\)This uses the sandboxing profile forpure computationas provided in Mac OS X Leopard and later\. This is supplemented by resource limiting via`setrlimit\(2\)`\.[capsicum\(4\)](https://www.freebsd.org/cgi/man.cgi?query=capsicum&sektion=4)\([FreeBSD](https://www.freebsd.org/)\)Uses the capabilities facility on[FreeBSD](https://www.freebsd.org/)10 and later\. This is supplemented by resource limiting with`setrlimit\(2\)`\.Since validation occurs within the sandbox, special care must be taken that validation routines don't access the environment \(e\.g\., by opening files, network connections, etc\.\), as the child**might**be abruptly killed by the sandbox facility\. \(Not all sandboxes do this\.\) If required, this kind of validation can take place after the parse validation sequence\. The connection delegator is similar, but has different sandboxing rules, as it must manage an open socket connection and respond to new requests\. ## testing kcgiis shipped with a fully automated testing framework executed with`make regress`\. To test your own applications, use the[kcgiregress\(3\)](https://kristaps.bsd.lv/kcgi/kcgiregress.3.html)library\. This framework acts as a mini\-webserver, listening on a local port, translating an HTTP document into a minimal CGI request, and passing the request to akcgiCGI client\. For internal tests, test requests are constructed with[libcurl](https://curl.haxx.se/libcurl/)\. The binding local port is fixed: if you plan on running the regression suite, you may need to tweak its access port\. The testing framework is used by the GitHub[Actions](https://github.com/kristapsdz/kcgi/actions)to make sure that all commits pass the regression tests on all supported systems \(including with compiler sanitisation\)\. Another testing framework exists for use with the[American fuzzy lop](http://lcamtuf.coredump.cx/afl/)\. To use this, you'll need to compile the`make afl`target with your compiler of choice, e\.g\.,`make clean`, then`make afl CC=afl\-gcc`\. Then run the`afl\-fuzz`tool on the`afl\-multipart`,`afl\-plain`, and`afl\-urlencoded`binaries using the test cases \(and dictionaries, for the first\) provided\. ## performance Security comes at a price—but not a stiff price\. By design,kcgiincurs overhead in three ways: first, spawning a child to process the untrusted network data; second, enacting the sandbox framework; and third, passing parsed pairs back to the parent context\. In the case of running CGI scripts,kcgiperformance is bound to the operating system's ability to spawn and reap processes\. For FastCGI, the bottleneck becomes the transfer of data\.

Similar Articles

A Modern Web App in C

Hacker News Top

作者分享了如何用 C 语言和 CGI 协议构建并部署一款现代商业 Web 产品(marketyour.games):单个静态链接二进制、SQLite 文件、仅三个依赖库,无框架、无容器,部署即替换文件、零停机。文章论证了在 2026 年用 C + OpenBSD httpd + SQLite(BCHS 栈)写真正的生产级 Web 应用依然可行且极具简洁性。

KC3 v0.1.17 released

Lobsters Hottest

KC3 v0.1.17 released with incremental compilation for 5x faster loading, binary database logging, a new HTTPS client, and various bug fixes.

agentc - a minimal agent in C: under 1 MB, no runtime

Reddit r/AI_Agents

agentc 是一个用 C 编写的极简可扩展编码代理:单个静态二进制不到 1 MB、无 libc,通过 MCP 处理外部工具,并提供带版本的 C ABI 支持进程内扩展。项目支持 macOS/Windows 运行时动态加载扩展,作者希望与社区讨论 MCP 与进程内扩展的边界划分。

@10xmylife: 这个工具好

X AI KOLs Following

KIGI CLI 0.1.5版本更新,新增支持5个OAuth提供商和24个基于API的提供商,包括Kimi Coding、ChatGPT、Grok xAI、Claude、GitHub Copilot。这是一个完全开源的支持图工程的CLI工具。

byJoey/cfnew

GitHub Trending (daily)

CFnew is a proxy tool based on Cloudflare Workers/Pages, supporting multiple protocols such as VLESS, Trojan, xhttp. It has built-in latency testing, subscription conversion, and a graphical management panel. The v2.9.8 update implements internal subscription conversion, no longer relying on external services, and optimizes transfer performance.