fits_open_file can copy arbitrary paths before validation

fitsopenfile can copy arbitrary paths before validation

fits_open_file passes the filename through CFITSIO’s parser first. The library splits out protocol prefixes, filter expressions, and the outfile clause before it gets to FITS validation, so a bad payload does not stop the early file handling.

That matters because the filename is not just a locator. It can become a copy instruction, and the copy happens before the library has any reason to reject the content as non-FITS.

Local paths still get touched before the library gives up

A local path can still be opened and copied even when the final FITS check fails. A string such as /etc/passwd(/workspace/foo) is enough to make CFITSIO touch the source and write to the chosen destination before the operation collapses.

The failure mode is dull in the worst way. The application thinks it is rejecting an invalid file, while CFITSIO has already done the interesting part.

A harmless metadata query can trigger the extra work

Some of the side effects show up after an open followed by a metadata query. That is the sort of delay that hides the problem during casual testing, because the initial call looks harmless until a later read or header lookup wakes the parser up again.

Do not assume a failed open is the only thing worth watching. If the filename was attacker-controlled, the library may already have copied data or reached into a path the caller never intended to expose.

Network handlers widen the blast radius into SSRF and remote fetches

CFITSIO registers more than plain local file handling. Prefixes such as http://, https://, ftp://, ftps://, and root:// route the string into backend drivers, and that turns a filename parameter into a network fetch.

http, https, ftp, ftps, and root:// do not behave like plain filenames

These handlers are not treated as simple path strings. http:// and ftp:// have long-standing raw socket code behind them, while the TLS variants delegate to libcurl, so the parsing step can end up building and sending requests, not just opening a file.

That is enough to create SSRF conditions when the caller accepts user input for a filename. A request that was meant to stay local can reach internal hosts, remote archives, or any endpoint the process can see.

Raw socket handling and driver registration decide what gets fetched

CFITSIO uses driver registration to map prefixes to handler functions. Once a prefix is registered, the filename parser can hand control to that backend, which decides whether the input is read, written, created, or fetched over the network.

root:// is a good reminder that the boundary is not “file” versus “URL”. The handler list decides the behaviour, and the filename syntax decides which handler gets a turn.

Lock the boundary at the caller, not after fits_open_file returns

Treat the filename as untrusted before it reaches CFITSIO. If the application only expects local FITS files, reject protocol prefixes, reject outfile clauses, and avoid passing raw user input into fits_open_file at all.

Where remote access is needed, make the allowed prefixes explicit and narrow. A broad allow-list that includes http, ftp, or root:// is an invitation to fetch things that were never meant to leave the machine.

The caller also needs to control the destination path, not the library. If CFITSIO is allowed to write into an attacker-chosen outfile, the read path stops being read-only and starts behaving like a file copy primitive.

Verify the path handling with malformed local files and controlled remote inputs

Test with local junk files that are valid enough to trigger parsing but invalid enough to fail FITS checks. Then test with controlled remote endpoints that log requests and return non-FITS content, because the dangerous behaviour sits in the transport and copy steps, not in the final payload.

A useful test case is a filename that looks boring at first glance but includes an outfile clause or a protocol prefix. If the code path still opens sockets or writes to disk after the first failure, the boundary is in the wrong place.

Related posts

Agentic AI still needs domain judgement

Agentic AI can write the thing, but it still cannot tell you whether the thing is right. That is where domain expertise matters, because a clean config or neat bit of glue logic can still be wrong in...

Weekly Tech Digest | 06 Jul 2026

Stay updated with the latest in tech! This digest covers AI ethics, auto industry shifts, and the impact of politics on technology, exploring today's pressing issues.

wolfCOSE zero-allocation parsing in embedded C

wolfCOSE looks sensible only if you care about what your firmware actually has to carry. I like that, because on small targets the wrong crypto feature can cost more than the message itself, and there...