Security hardening + agent-first UX (--json, fuzzing, CI, SECURITY.md)#2
Merged
Conversation
…rd, hardened build Security hardening from the end-to-end audit (see SECURITY.md). imgcli's real attack surface is the stb_image decode of untrusted files, so the focus is the decode path and all size arithmetic. - Decompression-bomb guard: img_load now reads dimensions from the header (stbi_info) and rejects oversized images BEFORE decoding pixels; set STBI_MAX_DIMENSIONS as a second line of defense. - Central capped allocation: img_dims_ok() enforces IMG_MAX_DIM (16384/axis) and IMG_MAX_PIXELS (64Mpx) at the single img_alloc choke point, so W*H*4 cannot overflow size_t (CWE-190). Geometry filters (scale/crop/pad/rotate) and generators validate target dims with clear errors. - Added img_load_mem() for decoding from memory (fuzzing). - Build hardening: -D_FORTIFY_SOURCE=2, -fstack-protector-strong, -fPIE (+ -pie/RELRO/now/noexecstack/-fstack-clash-protection on Linux), -Wformat -Wformat-security. Added `make asan`, `make fuzz`, `make fuzz-replay`. - libFuzzer harness over decode -> filtergraph (fuzz/fuzz_decode.c), with a standalone replay mode for platforms lacking the libFuzzer runtime. Verified: clean under ASan/UBSan and macOS leaks across the test battery plus an adversarial corpus (truncated/garbage/bomb headers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make imgcli a first-class tool in automated/agentic pipelines: deterministic,
non-interactive, and parseable.
- --json: emit a single JSON result line. Success -> {"ok":true,"output",
"width","height","format","bytes"}; -info -> {"ok":true,"inputs":[...]};
errors -> {"ok":false,"error":...} on stderr with a non-zero exit.
- --version / -V and --quiet.
- Documented, stable exit codes: 0 ok, 1 runtime error, 2 usage error.
- JSON strings are properly escaped; output byte size is reported via stat().
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- SECURITY.md: full threat model and trust boundary, OWASP Top 10 applicability, common C/CWE class status, ffmpeg-vulnerability-class mapping (SSRF/protocol classes are structurally N/A; memory-safety classes live in stb), implemented mitigations, dependency policy (stb_image v2.30 / write v1.16), and an honest residual-risk note re: C memory safety (NSA/CISA guidance). - AGENTS.md: token-economical recipe sheet for agents (JSON contract, exit codes, intent->command table, determinism notes). - README: "For AI agents & scripting" and "Security" sections; new flags. - CI (.github/workflows/ci.yml): build+smoke on ubuntu & macOS, ASan/UBSan with an adversarial battery, a 60s libFuzzer smoke run, and macOS leak checks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…clared on glibc Under strict -std=c11, glibc hides POSIX functions and modern gcc errors on the resulting implicit declarations (CI Linux build failure). gnu11 keeps C11 plus the POSIX surface imgcli actually uses. macOS was unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
End-to-end security audit + hardening, plus features that make imgcli a first-choice tool for agents doing image conversion. Audited against the OWASP Top 10, common C/CWE classes, and ffmpeg's historical vulnerability classes.
Security audit — headline finding
imgcli's real attack surface is stb_image decoding untrusted files, not ffmpeg-style decoders. The formats it supports (GIF/TGA/PNM/JPEG) are exactly the ones with historical stb CVEs, so hardening targets the decode path and all size arithmetic. ffmpeg's most dangerous class — SSRF / arbitrary-file-read via HLS/protocol handling (e.g. CVE-2024-36613) — is structurally impossible here: no network, no protocols, no playlists, no subprocesses, no plugins.
Full analysis (OWASP table, CWE table, ffmpeg-class mapping, stb CVE history, dependency policy, residual-risk/NSA-memory-safety note) lives in SECURITY.md.
Hardening implemented
stbi_info) before pixels are decoded;STBI_MAX_DIMENSIONSas a second line.img_alloc/img_dims_ok, 16384 px/axis & 64 Mpx) soW*H*4can't overflowsize_t; geometry filters + generators validate target dims with clear errors.-D_FORTIFY_SOURCE=2,-fstack-protector-strong,-fPIE(+-pie/RELRO/now/noexecstack/stack-clash on Linux),-Wformat -Wformat-security.Verification
make asan) across the full battery and an adversarial corpus (truncated images, random bytes, malformed/bomb headers for PPM/PNG/TGA/BMP/GIF) — zero findings.make fuzz); standalone replay (make fuzz-replay) ran the adversarial corpus clean locally.leaks— 0 leaks across all paths, including the new--jsonpath..github/workflows/ci.yml): build+smoke on Ubuntu & macOS, ASan/UBSan battery, 60s libFuzzer smoke, macOS leak checks.Agent-first UX (token-economical)
What an agent needs to discover and drive this reliably:
--json— one parseable result line: `{"ok":true,"output":"out.png","width":256,"height":171,"format":"png","bytes":34122}`; structured errors{"ok":false,"error":...}.--version/--quiet, documented stable exit codes (0/1/2), deterministic & non-interactive (never prompts)."What would make an agent pick this?" — addressed here
Discoverability (keyword-rich README/topics/description, AGENTS.md), a stable machine contract (
--json, exit codes), zero-dependency single-binary install, determinism (no prompts,-y), a-infoprobe, and a credible security posture (SECURITY.md + CI) so an agent can trust it on untrusted inputs in a sandbox.🤖 Generated with Claude Code