Library for creating Python executables compatible with LaTeX restricted shell escape
Project description
latexrestricted — Python library for creating executables compatible with LaTeX restricted shell escape
This Python package is designed to simplify the process of creating Python executables compatible with LaTeX restricted shell escape. Restricted shell escape allows LaTeX to run trusted executables as part of compiling documents. These executables have restricted access to the file system and restricted ability to launch subprocesses.
latexrestricted provides access to LaTeX configuration and implements
wrappers around Python's
pathlib.Path and
subprocess.run()
that follow LaTeX security settings.
Usage considerations
Importing
latexrestricted should be imported as soon as possible during the
initialization of an executable. When it is imported, it sets the current
working directory as the TeX working directory. If it is imported after the
current working directory is changed, then the TeX working directory will be
set incorrectly and security restrictions will fail.
Failure modes on systems with multiple TeX installations
latexrestricted works correctly when used on systems with no more than one
TeX Live installation and no more than one
MiKTeX installation. If multiple TeX Live
installations or multiple MiKTeX installations are present, it is not always
possible for latexrestricted to determine the correct TeX Live or MiKTeX
installation, and in these cases the first installation on PATH is used.
In these cases, latexrestricted may fail to return the correct TeX
configuration values, and there is no way to detect this. See
LatexConfig._init_tex_paths() for implementation details.
-
Multiple TeX Live installations: The correct installation will be used under non-Windows operating systems. Under Windows, the first installation on
PATHis used. -
Multiple MiKTeX installations: Under all operating systems, the first installation on
PATHis used.
The user can avoid any issues with multiple installations by modifying PATH
to put the correct TeX Live or MiKTeX installation first.
LaTeX configuration
from latexrestricted import latex_config
The latex_config instance of the LatexConfig class provides access to
LaTeX configuration and related environment variables. If there are errors in
determining LaTeX configuration (for example, a TeX installation cannot be
located), then latexrestricted.LatexConfigError is raised.
latex_config attributes and properties
Paths:
-
tex_cwd: str: Current working directory whenlatexrestrictedwas first imported. -
texlive_bin: str | Noneandtexlive_kpsewhich: str | None: If an executable usinglatexrestrictedis launched via\ShellEscapewith TeX Live, these will be the paths to the TeX Livebin/directory and the TeX Livekpsewhichexecutable. Otherwise, both areNone.TeX Live is detected by the absence of a
TEXSYSTEMenvironment variable, or by this variable having a value other thanmiktex. Under non-Windows operating systems, theSELFAUTOLOCenvironment variable set bykpathseais used to locate the TeX Live binary directory, so it will be correct even on systems with multiple TeX Live installations. Under Windows, shell escape executables are often launched with TeX Live's executable wrapperrunscript.exe, which overwritesSELFAUTOLOCwith the location of the wrapper. In this case, the TeX Live binary directory is located by using Python'sshutil.which()to searchPATHfor atlmgrexecutable with accompanyingkpsewhich. On systems with multiple TeX Live installations, this will give the first TeX Live installation onPATH, which is not guaranteed to be correct unless the user ensures that the correct installation has precedence onPATH. -
miktex_bin: str | None,miktex_initexmf: str | None, andmiktex_kpsewhich: str | None: If an executable usinglatexrestrictedis launched via\ShellEscapewith MiKTeX, these will be the paths to the MiKTeXbin/directory and the MiKTeXinitexmfandkpsewhichexecutables. Otherwise, all areNone.MiKTeX is detected by checking the
TEXSYSTEMenvironment variable for the valuemiktex.TEXSYSTEMonly declares that MiKTeX is in use; unlike the TeX Live case withSELFAUTOLOC,TEXSYSTEMdoes not give the location of TeX binaries. The location of TeX binaries is determined using Python'sshutil.which()to searchPATHfor aninitexmfexecutable with accompanyingkpsewhich. On systems with multiple MiKTeX installations, this will give the first MiKTeX installation onPATH, which is not guaranteed to be correct unless the user ensures that the correct installation has precedence onPATH.
File system access:
-
can_read_dotfiles: bool,can_read_anywhere: bool,can_write_dotfiles: bool,can_write_anywhere: bool: These summarize the file system security settings for TeX Live (openin_anyandopenout_anyintexmf.cnf) and MiKTeX ([Core]AllowUnsafeInputFilesand[Core]AllowUnsafeOutputFilesinmiktex.ini). The*dotfileproperties describe whether dotfiles (files with names beginning with.) can be read/written. The*anywhereproperties describe whether files anywhere in the file system can be read/written, or only those under the current working directory,TEXMFOUTPUT, andTEXMF_OUTPUT_DIRECTORY. -
can_restricted_shell_escape: bool: This describes whether restricted shell escape is possible. It is true when restricted shell escape is enabled and also when full shell escape is enabled. It is based on TeX Live'sshell_escapeintexmf.cnfand MiKTeX's[Core]ShellCommandModeinmiktex.ini. -
prohibited_write_file_extensions: frozenset[str] | None: Under Windows (including Cygwin), this is a frozen set of file extensions that cannot be used in writing files. Under other operating systems, this isNone.All file extensions are lower case with a leading period (for example,
.exe). These are determined from thePATHEXTenvironment variable, or use a default fallback ifPATHEXTis not defined or when under Cygwin.
Other LaTeX configuration variables and environment variables:
-
TEXMFHOME: str | None: Value ofTEXMFHOMEobtained fromkpsewhichorinitexmf. -
TEXMFOUTPUT: str | None: Value ofTEXMFOUTPUTobtained from environment variable if defined and otherwise fromkpsewhichorinitexmf. -
TEXMF_OUTPUT_DIRECTORY: str | None: Value ofTEXMF_OUTPUT_DIRECTORYobtained from environment variable. -
restricted_shell_escape_commands: frozenset[str]: Permitted restricted shell escape executables. Obtained from TeX Live'sshell_escape_commandsintexmf.cnfor MiKTeX's[Core]AllowedShellCommands[]inmiktex.ini.Note that this will contain permitted restricted shell escape executables even when shell escape is completely disabled; it cannot be used to determine whether restricted shell escape is permitted. See
can_restricted_shell_escapeto determine whether restricted shell escape is permitted.
latex_config methods
-
kpsewhich_find_config_file(file: str): Usekpsewhichin a subprocess to find a configuration file (kpsewhich -f othertext <file>). Returnskpsewhichoutput as a string orNoneif there was no output. -
kpsewhich_find_file(file: str, *, cache: bool = False): Usekpsewhichin a subprocess to find a file (kpsewhich <file>). Returnskpsewhichoutput as a string orNoneif there was no output. The optional argumentcachecacheskpsewhichoutput to minimize subprocesses. This can be useful when the file system is not being modified andkpsewhichis simply returning values from its own cache.
Restricted file system access
TeX limits file system access. The file system security settings for TeX Live
(openin_any and openout_any in texmf.cnf) and MiKTeX
([Core]AllowUnsafeInputFiles and [Core]AllowUnsafeOutputFiles in
miktex.ini) determine whether dotfiles can be read/written and whether files
anywhere in the file system can be read/written, or only those under the
current working directory, TEXMFOUTPUT, and TEXMF_OUTPUT_DIRECTORY.
The latexrestricted package provides RestrictedPath subclasses of Python's
pathlib.Path that respect
these security settings or enforce more stringent security. Under Python 3.8,
these subclasses backport the methods .is_relative_to() and .with_stem()
from Python 3.9. When these subclasses are used to modify the file system,
latexrestricted.PathSecurityError is raised if reading/writing a given path
is not permitted.
With RestrictedPath classes, relative paths are always relative to the TeX
working directory. If the current working directory has been changed to
another location (for example, via os.chdir()), then it will temporarily be
switched back to the TeX working directory during any RestrictedPath
operations that access the file system.
The SafeWrite* classes should be preferred unless access to additional
write locations is absolutely necessary. When multiple TeX Live
installations are present under Windows or multiple MiKTeX installations are
present under all operating systems, there is no guarantee that
latexrestricted will find the correct installation and thus use the correct
TeX configuration, unless PATH has been modified to put the correct
installation first.
from latexrestricted import <RestrictedPathClass>
RestrictedPath classes
BaseRestrictedPath
This is the base class for RestrictedPath classes. It cannot be used
directly. Subclasses define methods .readable_dir(), .readable_file(),
.writable_dir(), and .writable_file() that determine whether a given path
is readable/writable. Most methods for opening, reading, writing, replacing,
and deleting files as well as methods for creating and deleting directories
are supported. Methods related to modifying file permissions and creating
links are not supported. Unsupported methods raise NotImplementedError.
StringRestrictedPath classes
-
StringRestrictedPath: This follows the approach taken in TeX's file system security. TeX configuration determines whether dotfiles are readable/writable and which locations are readable/writable. Paths are analyzed as strings; the file system is never consulted. When read/write locations are restricted, paths are restricted using the following criteria:-
All relative paths are relative to the TeX working directory.
-
All absolute paths must be under
TEXMF_OUTPUT_DIRECTORYandTEXMFOUTPUT. -
Paths cannot contain
..to access a parent directory, even if the parent directory is a valid location.
When read/write locations are restricted, it is still possible to access locations outside the TeX working directory,
TEXMF_OUTPUT_DIRECTORY, andTEXMFOUTPUTif there are symlinks in those locations.Under Windows (including Cygwin), writing files with file extensions in
PATHEXT(for example,.exe) is also disabled. -
-
SafeStringRestrictedPath: Same asStringRestrictedPath, except that TeX configuration is ignored and all security settings are at maximum: dotfiles cannot be read/written, and all reading/writing is limited to the TeX working directory,TEXMF_OUTPUT_DIRECTORY, andTEXMFOUTPUT. -
SafeWriteStringRestrictedPath: Same asStringRestrictedPath, except that TeX configuration for writing is ignored and all security settings related to writing are at maximum.
ResolvedRestrictedPath classes
-
ResolvedRestrictedPath: This resolves any symlinks in paths using the file system before determining whether paths are readable/writable. TeX configuration determines whether dotfiles are readable/writable and which locations are readable/writable. When read/write locations are restricted, paths are restricted using the following criteria:-
Resolved paths must be under the TeX working directory, resolved
TEXMF_OUTPUT_DIRECTORY, or resolvedTEXMFOUTPUT. -
All relative paths are resolved relative to the TeX working directory.
-
Unlike
StringRestrictedPath, paths are allowed to contain.., andTEXMF_OUTPUT_DIRECTORYandTEXMFOUTPUTcan be accessed via relative paths. This is possible since paths are fully resolved with the file system before being compared with permitted read/write locations.
Because paths are resolved before being compared with permitted read/write locations, it is not possible to access locations outside the TeX working directory,
TEXMF_OUTPUT_DIRECTORY, andTEXMFOUTPUTvia symlinks in those locations.Under Windows (including Cygwin), writing files with file extensions in
PATHEXT(for example,.exe) is also disabled. -
-
SafeResolvedRestrictedPath: Same asResolvedRestrictedPath, except that TeX configuration is ignored and all security settings are at maximum: dotfiles cannot be read/written, and all other reading/writing is limited to the TeX working directory,TEXMF_OUTPUT_DIRECTORY, andTEXMFOUTPUT. -
SafeWriteResolvedRestrictedPath: Same asResolvedRestrictedPath, except that TeX configuration for writing is ignored and all security settings related to writing are at maximum.
RestrictedPath class methods
-
tex_cwd() -> Self: TeX working directory. -
TEXMFOUTPUT() -> Self | None: Path ofTEXMFOUTPUTfrom LaTeX configuration or environment variable, orNoneif not defined. -
TEXMF_OUTPUT_DIRECTORY() -> Self | None: Path ofTEXMF_OUTPUT_DIRECTORYfrom environment variable, orNoneif not defined. -
tex_roots() -> frozenset[Self]: All root locations where TeX might write output, under default configuration with restricted access to the file system. This includestex_cwd()plusTEXMFOUTPUT()andTEXMF_OUTPUT_DIRECTORY()if they are defined. -
tex_roots_resolved() -> frozenset[Self]: Same astex_roots()except all paths are resolved with the file system. -
tex_roots_with_resolved() -> frozenset[Self]: Union oftex_roots()andtex_roots_resolved(). -
tex_openout_roots() -> tuple[Self]: Locations where TeX will attempt to write with\openout, in order. The first element of the tuple isTEXMF_OUTPUT_DIRECTORY()if notNoneand otherwisetex_cwd(). IfTEXMFOUTPUT()is notNoneand is not already in the tuple, then it is the second element.TeX attempts to write to
TEXMFOUTPUT(if defined) when the default write location (TEXMF_OUTPUT_DIRECTORYif defined, else TeX working directory) is read-only. -
tex_texmfoutput_roots() -> frozenset[Self]:TEXMFOUTPUT()and/orTEXMF_OUTPUT_DIRECTORY()if they are defined.
Restricted subprocesses
When LaTeX runs with restricted shell escape, only executables specified in
TeX configuration can be executed via \ShellEscape. The latexrestricted
package allows these same executables to run in subprocesses via
restricted_run(). This is a wrapper around Python's
subprocess.run().
from latexrestricted import restricted_run
restricted_run(args: list[str], allow_restricted_executables: bool = False)
-
It is always possible to run
kpsewhich(includingmiktex-kpsewhich) andinitexmf. These are necessary to access TeX configuration values.Running other executables allowed by TeX configuration for restricted shell escape requires the optional argument
allow_restricted_executables=True. In this case, TeX configuration is checked to determine whether restricted shell escape is enabled, although this should be redundant iflatexrestricteditself is being used in a restricted shell escape executable. -
When
allow_restricted_executables=True, the executable must be in the same directory askpsewhichorinitexmf, as previously located during TeX configuration detection, or the executable must exist onPATH, as found by Python'sshutil.which().The executable must not be in a location writable by LaTeX. For added security, locations writable by LaTeX cannot be under the executable parent directory.
-
The executable cannot be a batch file (no
*.bator*.cmd): https://docs.python.org/3/library/subprocess.html#security-considerations. This is enforced by requiring*.exeunder Windows and completely prohibiting*.batand*.cmdeverywhere. -
The subprocess runs with
shell=False.
restricted_run() will raise latexrestricted.ExecutableNotFoundError if an
executable (args[0]) cannot be found in the same directory as kpsewhich or
initexmf, or on PATH. It will raise
latexrestricted.UnapprovedExecutableError when the executable is not in the
approved list of executables from LaTeX configuration
(latex_config.restricted_shell_escape_commands). It will raise
latexrestricted.ExecutablePathSecurityError if the executable is found and
is in the approved list, but is in an insecure location relative to locations
writable by LaTeX.
Security limitations with TeX Live and TEXMFOUTPUT
TeX Live allows TEXMFOUTPUT to be set in a texmf.cnf config file. In this
case, latexrestricted will retrieve the value of TEXMFOUTPUT by running
kpsewhich --var-value TEXMFOUTPUT in a subprocess. If the user has modified
TEXMFOUTPUT to an unsafe value in a texmf.cnf config file, then the
kpsewhich executable (and all other TeX-related executables) are potentially
compromised, and latexrestricted cannot detect this until after running
kpsewhich.
It is possible to set TEXMFOUTPUT to unsafe values in a texmf.cnf config
file. For example, if TEXMFOUTPUT is set to a location in the file system
that contains executables, this could allow LaTeX documents to modify those
executables or their resources. With TeX Live, latexrestricted retrieves
the value of TEXMFOUTPUT by running kpsewhich. However, the kpsewhich
executable itself could be compromised if TEXMFOUTPUT is set to a directory
that contains the kpsewhich executable (or other parts of a TeX
installation). If latexrestricted detects an unsafe value of TEXMFOUTPUT,
it raises latexrestricted.LatexConfigError, but this is only possible
after running the potentially compromised kpsewhich executable to obtain
the value of TEXMFOUTPUT. (And if kpsewhich is compromised, there is
always the possibility that it will not return the true value of
TEXMFOUTPUT.)
While raising a security-related error after running the potentially
compromised executable is not ideal, this will typically have a negligible
impact on overall security. If TEXMFOUTPUT is set to a directory that
contains the kpsewhich executable (or other parts of a TeX installation),
then all other TeX-related executables are also potentially compromised. If
latexrestricted is being used in a Python executable designed for LaTeX
shell escape, then presumably a LaTeX executable is already running, and LaTeX
may invoke additional trusted executables such as kpsewhich in shells.
Thus, before latexrestricted ever runs kpsewhich to retrieve the value of
TEXMFOUTPUT, potentially compromised executables would already be running.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file latexrestricted-0.6.2.tar.gz.
File metadata
- Download URL: latexrestricted-0.6.2.tar.gz
- Upload date:
- Size: 28.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d51d21a41197a581ff29c0f818551f16fa0e6890def929799ac0bde762a7aa60
|
|
| MD5 |
5baee23e1d5895948d0f34fa6525031d
|
|
| BLAKE2b-256 |
69c25174b64463f9530c3d19c47606140b098b2ed6a6cb4ceac8c34b616bafdd
|
File details
Details for the file latexrestricted-0.6.2-py3-none-any.whl.
File metadata
- Download URL: latexrestricted-0.6.2-py3-none-any.whl
- Upload date:
- Size: 27.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
993bcc1c2a0484e95ce8f167bd8ec19de18cc7386cdb2d1f55d839d036eed590
|
|
| MD5 |
4bd83ab7824cff8302fade973639de66
|
|
| BLAKE2b-256 |
3c9ab99b0f9516a529efa89e5d1d1abeba620d73beebcceeb5f50f3a01970c8e
|