Secure Exceptions

PathGuardrails and higher-level wrappers (mail guardrails, future storage helpers) raise PathSecurityError whenever filesystem access breaches the configured policies. Keep this exception handy when integrating guardrails so you can differentiate between OS-level errors and policy violations.

Exception Hierarchy

KstlibError
├── PathSecurityError              # filesystem guardrails (also inherits RuntimeError)
└── PasswordError                  # password hashing (also inherits RuntimeError)
    └── InvalidPasswordHashError   # stored hash is corrupt or not a valid Argon2 hash

Note

Guardrails never bypass the operating system. They provide a consistent policy layer (auto-create roots, permission checks, traversal detection), but you still need to provision secure directories and ACLs yourself.

Quick overview

  • PathSecurityError inherits from RuntimeError and signals traversal attempts, wrong file types, or permissions that exceed the allowed mask defined by the active GuardPolicy.

  • PasswordError (under KstlibError, also a RuntimeError) signals a password hashing failure: the optional argon2-cffi backend is not installed, the password is not str/bytes, it exceeds MAX_PASSWORD_LENGTH, or the backend itself failed.

  • InvalidPasswordHashError (under PasswordError) is raised when a stored value is not a valid Argon2 hash. Note that verify_password returns False on a wrong password and raises InvalidPasswordHashError only when the stored hash itself is corrupt or malformed.

Usage patterns

Resolving safe files

from pathlib import Path
from kstlib.secure import PathGuardrails, PathSecurityError, STRICT_POLICY

guard = PathGuardrails(Path("~/.cache/kstlib"), policy=STRICT_POLICY)

try:
    template = guard.resolve_file("templates/newsletter.html")
except PathSecurityError as error:
    LOGGER.error("Blocked unsafe path", error=error)

Handling traversal attempts

from kstlib.secure import PathGuardrails, PathSecurityError, RELAXED_POLICY

guard = PathGuardrails("/srv/kstlib", policy=RELAXED_POLICY)

try:
    guard.resolve_file("../etc/passwd")
except PathSecurityError:
    print("Traversal prevented by guardrails")

Verifying a password safely

from kstlib.secure import InvalidPasswordHashError, verify_password

try:
    ok = verify_password(submitted_password, stored_hash)
except InvalidPasswordHashError:
    # The stored hash is corrupt or not an Argon2 hash: treat as an integrity
    # error, never as a successful login.
    ok = False

if not ok:
    reject()

Exception reference

exception kstlib.secure.fs.PathSecurityError[source]

Bases: KstlibError, RuntimeError

Raised when filesystem guardrails detect a security violation.

exception kstlib.secure.passwords.PasswordError[source]

Bases: KstlibError, RuntimeError

Raised when a password hashing operation cannot be completed.

exception kstlib.secure.passwords.InvalidPasswordHashError[source]

Bases: PasswordError

Raised when a stored value is not a valid Argon2 hash.

Module reference

Filesystem guardrails utilities for securing file access.

Example

Basic usage with a temporary directory:

>>> import tempfile
>>> from kstlib.secure import PathGuardrails, STRICT_POLICY
>>> with tempfile.TemporaryDirectory() as tmpdir:
...     guard = PathGuardrails(tmpdir, policy=STRICT_POLICY)
...     guard.root.is_dir()
True
class kstlib.secure.fs.GuardPolicy(name, allow_external=False, auto_create_root=True, enforce_permissions=True, max_permission_octal=448)[source]

Bases: object

Configuration values defining how guardrails behave.

name

Human-friendly label used for diagnostics.

Type:

str

allow_external

When True, paths outside the root are accepted.

Type:

bool

auto_create_root

Automatically create the root directory when missing.

Type:

bool

enforce_permissions

Whether POSIX permissions should be validated.

Type:

bool

max_permission_octal

Maximum allowed permission mask (defaults to PRIVATE).

Type:

int

Example

>>> from kstlib.secure import GuardPolicy
>>> policy = GuardPolicy(name="custom", allow_external=False)
>>> policy.name
'custom'
name: str
allow_external: bool
auto_create_root: bool
enforce_permissions: bool
max_permission_octal: int
__init__(self, name: 'str', allow_external: 'bool' = False, auto_create_root: 'bool' = True, enforce_permissions: 'bool' = True, max_permission_octal: 'int' = 448) None -> None
class kstlib.secure.fs.PathGuardrails(root, *, policy=GuardPolicy(name='strict', allow_external=False, auto_create_root=True, enforce_permissions=True, max_permission_octal=448))[source]

Bases: object

Validate and resolve paths relative to a trusted root.

Example

>>> import tempfile
>>> from kstlib.secure import PathGuardrails, RELAXED_POLICY
>>> with tempfile.TemporaryDirectory() as tmpdir:
...     guard = PathGuardrails(tmpdir, policy=RELAXED_POLICY)
...     guard.policy.name
'relaxed'
__init__(self, root: 'str | Path', *, policy: 'GuardPolicy' = GuardPolicy(name='strict', allow_external=False, auto_create_root=True, enforce_permissions=True, max_permission_octal=448)) 'None' -> None[source]

Initialise guardrails rooted at root while enforcing policy.

Raises:

PathSecurityError – If root does not exist or is not a directory.

property root: Path

Return the resolved guardrail root directory.

property policy: GuardPolicy

Return the policy associated with the guardrails.

resolve_file(self, candidate: 'str | Path') 'Path' -> Path[source]

Resolve candidate and ensure it points to an existing file.

Raises:

PathSecurityError – If path is not a file or is outside root.

resolve_directory(self, candidate: 'str | Path') 'Path' -> Path[source]

Resolve candidate and ensure it points to an existing directory.

Raises:

PathSecurityError – If path is not a directory or is outside root.

resolve_path(self, candidate: 'str | Path') 'Path' -> Path[source]

Resolve candidate relative to the guardrail root without type checks.

relax(self, *, allow_external: 'bool | None' = None) 'PathGuardrails' -> PathGuardrails[source]

Return a new guardrail instance with adjusted external allowances.

exception kstlib.secure.fs.PathSecurityError[source]

Bases: KstlibError, RuntimeError

Raised when filesystem guardrails detect a security violation.