SEC: Block figure.hooks from being loaded from file#31293
SEC: Block figure.hooks from being loaded from file#31293scottshambaugh wants to merge 1 commit intomatplotlib:mainfrom
figure.hooks from being loaded from file#31293Conversation
dc02fb5 to
1e0cb8e
Compare
1e0cb8e to
ec62f8c
Compare
ec62f8c to
7cb77cc
Compare
|
I'm sold on removing it from style files (it is not a "style"), but I'm less sold about dropping it from all config files. Once you can drop arbitrary files on disk the jig is up. Rather than go through https://devblogs.microsoft.com/oldnewthing/20060508-22/?p=31283 (and similar writing from the same author) has shaped my thinking on this. If the pre-requisite for getting code execution is the ability to write files as the user and trick them into running a program in our directory, then we already have as high or higher privileges than we can get via this mechanism. |
|
I tend to agree in general (and in this case because you'd need an extra poisoned python file). But I would push back on this for files which appear benign at first look. It's non-obvious that style files or matplotlibrc can cause code to execute, rather than merely setting flags or default values. I think the reasonable implicit assumption here is that style configurations are safe to pass around, and both humans and automated checkers could easily miss the security implications. A more restrictive position that might make sense is to not autoload matplotlibrc at all, and require the user to call a function to load a non-default one. |
|
I would definitely oppose such a change (in matplotlibrc files -- no opinion about style files). The fact that no use has been found on github suggests that we didn't really advertise the feature really well after introducing it (relatively recently) in #22316. However the feature can definitely be convenient to have at a global level (rather than being something you need to activate explicitly in every script); I uploaded my personal use cases to https://github.com/anntzer/mpl-azhooks (and mplcursors' "activation by environment variable" also benefits from it, see https://mplcursors.readthedocs.io/en/stable/#activation-by-environment-variable). Moreover, this change would only make sense if you also disallowed setting the backend in matplotlibrc files as well (which seems excessive to me), because 1) loading third-party backend modules (obviously) runs arbitrary python code, and 2) it is possible to write a "shim" backend module that starts by running arbitrary user-provided hooks (e.g., update "forbidden" rcParams) before loading and replacing itself by the real backend module (a quite hackish technique I had locally tried before having real figure hooks). (If this really goes through I guess that locally I'll switch to setting the |
anntzer
left a comment
There was a problem hiding this comment.
Disagree on restriction to matplotlibrc files, per the above.
|
Maybe a somewhat radical idea: Can we deactivate loading any matplotlibrc by default? The argument would be that the behavior is completely fixed and not dependent on some global state. Processing a matplotlibrc would be opt-in (either through an environment variable or in-code). This is conceptually similar to forcing a backend via MPLBACKEND or Users activating this would explicitly opt-into potentially dangerous behavior. |
|
I could agree with not loading matplotlibrc, except if specified by the (already existing) MATPLOTLIBRC environment variable. |
|
I think not loading a custom matplotlibrc by default is the more durable guard here, and closes this attack surface rather than us playing whack-a-mole with params that may or may not have side effects. Style files are explicitly opt-in, so I'm not as worried about those. I'll close this and open a separate issue for that. |
|
Issue here: #31346 |
PR summary
This adds
figure.hooksto a new_RCPARAMS_FROM_FILE_BLACKLISTvariable which blocks specific rcparams from being loaded from style files or matplotlibrc. Programmatic use likeplt.rcParams["figure.hooks"] = ...is unaffected.The
figure.hooksrcParam accepts a list of"module:callable"strings that are processed viaimportlib.import_module()and called on every new figure. A malicious style or matplotlibrc file combined with a python file in the working directory could load and execute that module.This is definitely a more involved attack vector since it requires a module on PATH, so I definitely see an argument for not bothering to restrict it. But I don't see a single non-empty
figure.hookswhen searching github, so IMO there's no downside: https://github.com/search?q=%22figure.hooks%3A+[%22&type=codeI think the new
_RCPARAMS_FROM_FILE_BLACKLISTvariable is more broadly useful, and we may (?) want to revisit gating LaTeX preambles this way (#31249).This is basically a more restrictive version of
style._STYLE_BLACKLIST, which should stay on its own since it's for blocking things that aren't style changes.AI Disclosure
Claude used for the audit, code changes made manually.
PR checklist