Skip to content

Security: offerrall/FuncToWeb

Security

docs/security.md

Security

FuncToWeb publishes functions; the boundary with the host application is explicit.

What FuncToWeb does guarantee

  • Input is validated before the function is called, recursively and against the declared contract. See types.md.
  • File references never escape their directory: /upload, /returns/{ref} and the pre-execution resolution all require a bare file name, with no separators, no . or .. and no absolute path. Both /returns/{ref} and the pre-execution resolution also require the final path to have its root directory as its immediate parent and to be an existing file. A .., a symbolic link pointing outside, a subdirectory or an absolute path from anywhere else are all rejected. See files.md and outputs.md.
  • A local path never leaves the server: a file travels as its reference in both directions. Whatever the client sends is a reference, and whatever a page publishes for a file —a prefill, an OpenForm opening, a default written in the signature— is a reference too. A file that storage does not own has no reference, so the page is not built: a prefill answers 400, an OpenForm answers 500, and a signature default makes the WebFunction impossible to build. A rejection names the file and not where it is kept: the storage directory is cut out of the message before it is emitted, so a 422 or a 400 from IsPathFile reads not an accepted file type: 'notas.bin'. See files.md.
  • A published reference is immutable: /upload responds 409 to any attempt to write it again —whether the file was already used or not— so knowing another user's reference does not let you replace their file. Once it has been used, the file is also permanent: the expiry of unused uploads never reaches it. See files.md.
  • /static/{path} serves nothing outside its two directories, although it does serve their subdirectories, and it responds 404 without distinguishing between "it is not there" and "you are not allowed to have it". See static-assets.md.
  • The interface writes all output as text, never as HTML.

All three containments, uploads, returns and static assets, rest on the same two checks: a filter on the name before anything touches the disk, and a resolution that has to land under the root directory. The names the filter refuses are in files.md, and what /static resolves against is in static-assets.md.

What belongs to the host application

  • Authentication and authorization. FuncToWeb provides none: what you mount is an APIRouter, and it inherits whatever the host application applies. run() protects nothing.
  • Per-file permissions and the life cycle of what is uploaded and returned.
  • Execution limits: FuncToWeb imposes no maximum time, no memory limit and no per-client concurrency limit.
  • Exposure of error messages: the message of an exception travels to the client as is, so a function that writes internal data into that message publishes it.

hidden hides, it does not protect

The hidden query parameter of a form opening takes a parameter out of view. That is all it does: the value still travels in the body of the execution, and anyone can call /invoke with a different one. A prefill does not lock a value either. See prefill.md.

The prefill travels in the URL

It stays in the browser history, in the Referer header and in the server access log. No channel available today avoids this, so data that must not be logged must not travel as a prefill.

The result travels to whoever embeds the page

An embedded page announces its runs to window.parent with a targetOrigin of "*" (sdk.md), so the outputs of a run reach the host whatever origin it is on. The page cannot narrow that: it does not know who embedded it, and asking it to guess would only trade an honest assumption for a false one. The assumption is the same as the prefill's, and it points the same way: whoever can embed a page can read what runs inside it, so a function whose outputs must not leave belongs in a space that is not embeddable from outside — which is the host application's boundary, not FuncToWeb's. A page nobody embeds announces nothing at all.

Related: limitations.md, files.md, http.md, sdk.md.

There aren't any published security advisories