Edit page in Livemark
(2026-10-08 21:15)

Security

Frictionless reads local files and downloads remote resources as instructed by the provided metadata (a resource path, a package profile, a remote reference $ref inside the profile, etc.). This page explains the risks and best practices to follow for untrusted metadata (e.g. for a validation API).

Validating trusted vs untrusted input

In the context of a local user validating their own trusted data, the command line frictionless validate --trusted flag, or the system context provides a way to disable overly cautious security checks.

In the context of validation of untrusted input, trusted must stay False (the default), and in case of a service, deployment measures described below are recommanded.

Note that the safety checks validate descriptors (the metadata provided as a dictionary, a file, or a URL). Values you pass yourself in the Python API, such as Resource('/any/path.csv'), are under your own responsibility.

What the default mode protects

When trusted is False (the default), local disk access provided by the metadata must stay inside the working directory. For a resource, the path, extrapaths, profile, dialect, and schema properties must be relative paths, without .., ~, or environment variables. The same rule applies to a package profile. A rejected path yields a path "..." is not safe error.

For a profile "$ref", additional rules apply:

When a profile "$ref" points to a non-existent JSON pointer or anchor, the error message names the pointer, but does not disclose the content of the referenced document: a "$ref" can target any file of the working directory, whose content may be confidential.

What the default mode does not protect

Best practices for a validation service

from frictionless import Package

report = Package.validate_descriptor(descriptor)
for error in report.errors:
    print(error.note)

Protecting a service against SSRF

To protect against Server-Side Request Forgery, here are some suggestions :

  1. Filter the outgoing network traffic at the infrastructure level: firewall, cloud security groups etc. Ideally, run the validation workers in a network segment without access to the internal network.
  2. Inject a hardened HTTP session. The session provided through system.use_context(http_session=...) is used for every remote metadata download. Resolve and validate the IP at the moment of connection, not beforehand, to defeat DNS rebinding: a check done before the request is sent can be bypassed by a DNS response that flips between a public and a private address. Use the standard-library ipaddress module for the check; the OWASP SSRF Prevention Cheat Sheet describes this pattern.
  3. If the acceptable remote resources are known, restrict them to this set, for example with a session adapter that only allows a fixed list of hosts.

Reference

System (class)

System (class)

System representation This class provides an ability to make system Frictionless calls. It's available as `frictionless.system` singletone.

Signature

system.supported_hooks (property)

A flag that indicates if resource, path or package is trusted.

Signature

ClassVar[List[str]]

system.trusted (property)

A flag that indicates if resource, path or package is trusted.

Signature

bool

system.onerror (property)

Type of action to take on Error such as "warn", "raise" or "ignore".

Signature

types.IOnerror

system.standards (property)

Setting this value user can use feature of the specific version. The default value is v2.

Signature

types.IStandards

system.http_session (property)

Return a HTTP session This method will return a new session or the session from `system.use_http_session` context manager

system.create_adapter (method)

Create adapter

Signature

(source: Any, *, control: Optional[Control] = None, basepath: Optional[str] = None, packagify: bool = False) -> Optional[Adapter]

Parameters

  • source (Any)
  • control (Optional[Control])
  • basepath (Optional[str])
  • packagify (bool)

system.create_loader (method)

Create loader

Signature

(resource: Resource) -> Loader

Parameters

  • resource (Resource): loader resource

system.create_parser (method)

Create parser

Signature

(resource: Resource) -> Parser

Parameters

  • resource (Resource): parser resource

system.deregister (method)

Deregister a plugin

Signature

(name: str)

Parameters

  • name (str): plugin name

system.detect_field_candidates (method)

Create candidates

Signature

() -> List[dict[str, Any]]

system.detect_resource (method)

Hook into resource detection

Signature

(resource: Resource) -> None

Parameters

  • resource (Resource): resource

system.register (method)

Register a plugin

Signature

(name: str, plugin: Plugin)

Parameters

  • name (str): plugin name
  • plugin (Plugin): plugin to register