Skip to content

chore(deps): update dependency mako to v1.3.12 [security]#969

Merged
bkeryan merged 1 commit intomasterfrom
users/renovate/pypi-mako-vulnerability
May 7, 2026
Merged

chore(deps): update dependency mako to v1.3.12 [security]#969
bkeryan merged 1 commit intomasterfrom
users/renovate/pypi-mako-vulnerability

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate Bot commented May 7, 2026

This PR contains the following updates:

Package Change Age Confidence
Mako (source) 1.3.111.3.12 age confidence

Mako vulnerable to path traversal via backslash URI on Windows in TemplateLookup

CVE-2026-44307 / GHSA-2h4p-vjrc-8xpq

More information

Details

Summary

On Windows, a URI using backslash traversal (e.g. \..\..\ secret.txt) bypasses the directory traversal check in Template.__init__ and the posixpath-based normalization in TemplateLookup.get_template(), allowing reads of files outside the configured template directory.

Details

The root cause is a mismatch between posixpath (used for URI normalization in get_template()) and os.path (used for file access via os.path.isfile() and validation via os.path.normpath() in Template.__init__). On Windows, os.path is ntpath, which treats \ as a path separator, while posixpath treats it as a literal character.

The vulnerability chain:

  1. get_template() strips only leading / via re.sub(r"^\/+", "", uri) and normalizes with posixpath — backslash \ is treated as a literal character, so \..\ secret.txt passes through with .. undetected.
  2. Template.__init__() validation uses os.path.normpath() — on Windows this resolves \..\ secret.txt to \secret.txt, which does not start with .., so the startswith("..") check passes.
  3. os.path.isfile() on Windows interprets \ as a path separator, resolving the .. traversal and finding files outside the template directory.
Affected code
  • mako/lookup.py: TemplateLookup.get_template() uses posixpath.normpath/posixpath.join for path construction but os.path.isfile() for existence check
  • mako/template.py: Template.__init__() URI validation uses os.path.normpath() which on Windows resolves backslash traversal to a form that passes the startswith("..") guard
Impact

If an application passes user-controlled template names or include paths to TemplateLookup.get_template(), an attacker on Windows may be able to load and disclose readable files outside the configured template directory. The primary impact is local file disclosure. If the targeted file contains Mako/Python template syntax, it may also be parsed and executed as a template.

Remediation

The fix should normalize backslashes to forward slashes early in the URI processing pipeline, before any path operations, to ensure consistent behavior across platforms.

Severity

  • CVSS Score: 8.7 / 10 (High)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

References

This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).


Configuration

📅 Schedule: (in timezone US/Central)

  • Branch creation
    • ""
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate Bot requested review from bkeryan, maxxboehme and zhindes as code owners May 7, 2026 01:07
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

Test Results

    48 files  +    30      48 suites  +30   1h 41m 49s ⏱️ + 1h 33m 7s
 3 209 tests + 2 971   2 555 ✅ + 2 317     653 💤 +   653  0 ❌ ±0  1 🔥 +1 
62 228 runs  +58 586  49 396 ✅ +45 754  12 830 💤 +12 830  1 ❌ +1  1 🔥 +1 

For more details on these errors, see this check.

Results for commit 5f0d6cb. ± Comparison against base commit 03987a7.

♻️ This comment has been updated with latest results.

@zhindes zhindes enabled auto-merge (squash) May 7, 2026 13:37
@bkeryan
Copy link
Copy Markdown
Collaborator

bkeryan commented May 7, 2026

build.yml validated that upgrading Mako didn't affect the codegen output.

This system test failure is not caused by the Mako upgrade:

=================================== ERRORS ====================================
_ ERROR at teardown of test___ai_task___register_wrong_every_n_samples_event___not_supported_by_device_error_raised[grpc_init_kwargs] _

init_kwargs = {'grpc_options': <nidaqmx.grpc_session_options.GrpcSessionOptions object at 0x0AAA5598>}

    @pytest.fixture(scope="function")
    def generate_task(init_kwargs) -> Generator[Callable[..., nidaqmx.Task]]:
        """Gets a factory function which can be used to generate new tasks.
    
        The closure of task objects will be done by this fixture once the test is complete.
        This fixture owns the task. Do not use it for test cases that destroy the task, or else you
        may get double-close warnings.
        """
>       with contextlib.ExitStack() as stack:

tests\conftest.py:509: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\Program Files (x86)\Python310-32\lib\contextlib.py:576: in __exit__
    raise exc_details[1]
C:\Program Files (x86)\Python310-32\lib\contextlib.py:561: in __exit__
    if cb(*exc_details):
generated\nidaqmx\task\_task.py:153: in __exit__
    self.close()
generated\nidaqmx\task\_task.py:362: in close
    raise first_exception
generated\nidaqmx\task\_task.py:357: in close
    event_handler.close()
generated\nidaqmx\_grpc_interpreter.py:75: in close
    raise self._event_stream_exception
generated\nidaqmx\_grpc_interpreter.py:79: in _thread_main
    for event_response in self._event_stream:
.tox\py310-grpc\lib\site-packages\grpc\_channel.py:538: in __next__
    return self._next()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <_MultiThreadedRendezvous of RPC that terminated with:
	status = StatusCode.UNKNOWN
	details = "DAQmx Every N Samples ...ot supported by the channel types or devices in your task.\n\nTask Name: _unnamedTask<2F4>\n\nStatus Code: -200980"}"
>

    def _next(self) -> Any:
        with self._state.condition:
            if self._state.code is None:
                event_handler = _event_handler(
                    self._state, self._response_deserializer
                )
                self._state.due.add(cygrpc.OperationType.receive_message)
                operating = self._call.operate(
                    (cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),),
                    event_handler,
                )
                if not operating:
                    self._state.due.remove(cygrpc.OperationType.receive_message)
            elif self._state.code is grpc.StatusCode.OK:
                raise StopIteration()
            else:
>               raise self
E               grpc._channel._MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
E               	status = StatusCode.UNKNOWN
E               	details = "DAQmx Every N Samples Transferred from Buffer Event is not supported by the channel types or devices in your task.
E               
E               Task Name: _unnamedTask<2F4>
E               
E               Status Code: -200980"
E               	debug_error_string = "UNKNOWN:Error received from peer  {grpc_status:2, grpc_message:"DAQmx Every N Samples Transferred from Buffer Event is not supported by the channel types or devices in your task.\n\nTask Name: _unnamedTask<2F4>\n\nStatus Code: -200980"}"
E               >

.tox\py310-grpc\lib\site-packages\grpc\_channel.py:939: _MultiThreadedRendezvous
================================== FAILURES ===================================
_ test___ai_task___register_wrong_every_n_samples_event___not_supported_by_device_error_raised[grpc_init_kwargs] _

ai_task = Task(name=_unnamedTask<2F4>)

    def test___ai_task___register_wrong_every_n_samples_event___not_supported_by_device_error_raised(
        ai_task: nidaqmx.Task,
    ) -> None:
        event_observer = EveryNSamplesEventObserver()
        ai_task.timing.cfg_samp_clk_timing(
            rate=10000.0, sample_mode=AcquisitionType.FINITE, samps_per_chan=1000
        )
    
>       with pytest.raises(nidaqmx.DaqError) as exc_info:
E       Failed: DID NOT RAISE <class 'nidaqmx.errors.DaqError'>

tests\component\test_task_events.py:435: Failed
=========================== short test summary info ===========================
FAILED tests/component/test_task_events.py::test___ai_task___register_wrong_every_n_samples_event___not_supported_by_device_error_raised[grpc_init_kwargs]
ERROR tests/component/test_task_events.py::test___ai_task___register_wrong_every_n_samples_event___not_supported_by_device_error_raised[grpc_init_kwargs]
1 failed, 2344 passed, 603 skipped, 27 xfailed, 10 xpassed, 1 error in 417.27s (0:06:57)
py310-grpc: exit 1 (430.14 seconds) C:\ar\_work\nidaqmx-python\nidaqmx-python> poetry run pytest --quiet --cov=generated/nidaqmx --cov-append --cov-report= --junitxml=test_results/system-py310-grpc.xml pid=8296
py310-grpc: FAIL ✖ in 7 minutes 47.72 seconds

@bkeryan bkeryan disabled auto-merge May 7, 2026 16:13
@bkeryan bkeryan merged commit 4aec527 into master May 7, 2026
62 of 65 checks passed
@bkeryan bkeryan deleted the users/renovate/pypi-mako-vulnerability branch May 7, 2026 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants