temporalio/sdk-python

Missing comma in sandbox restrictions leaves time.perf_counter_ns and process_time unrestricted

Summary

  • Context: The workflow sandbox in temporalio/worker/workflow_sandbox/_restrictions.py defines which time module functions are restricted during workflow execution to ensure deterministic behavior.

  • Bug: A missing comma between two strings on line 788 causes Python’s implicit string concatenation to merge "perf_counter_ns" and "process_time" into a single invalid entry "perf_counter_nsprocess_time".

  • Actual vs. expected: The restrictions set contains the invalid concatenated string instead of two separate entries, leaving time.perf_counter_ns and time.process_time unrestricted when they should trigger RestrictedWorkflowAccessError at runtime.

  • Impact: Workflows can call non-deterministic time measurement functions without restriction, violating workflow determinism guarantees.

Code with bug

"time": SandboxMatcher(
    use={
        "pthread_getcpuclockid",
        "get_clock_info",
        "localtime",
        "monotonic",
        "monotonic_ns",
        "perf_counter",
        "perf_counter_ns",
        "process_time",      # <-- BUG 🔴 Missing comma previously caused string concatenation
        "process_time_ns",
        "sleep",
        "time",
        "time_ns",
        "thread_time",
        "thread_time_ns",
        "tzset",
    },
    only_runtime=True,
),

Example

Python’s implicit string concatenation merges adjacent string literals when no comma separates them:

# With missing comma (buggy)
buggy_set = {
    "perf_counter",
    "perf_counter_ns" "process_time",  # Missing comma
    "process_time_ns",
}

# Result:
# {'perf_counter', 'perf_counter_nsprocess_time', 'process_time_ns'}
# Only 3 items – the two strings were concatenated


# With comma (correct)
correct_set = {
    "perf_counter",
    "perf_counter_ns",  # Comma present
    "process_time",
    "process_time_ns",
}

# Result:
# {'perf_counter', 'perf_counter_ns', 'process_time', 'process_time_ns'}
# 4 items – all separate

Test output confirms the bug:


Both time.perf_counter_ns() and time.process_time() are real Python functions that return non-deterministic values based on system state and timing.

Recommended fix

Add a comma between the two strings:

"time": SandboxMatcher(
    use={
        "pthread_getcpuclockid",
        "get_clock_info",
        "localtime",
        "monotonic",
        "monotonic_ns",
        "perf_counter",
        "perf_counter_ns",  // <-- FIX 🟢 Add comma here
        "process_time",
        "process_time_ns",
        "sleep",
        "time",
        "time_ns",
        "thread_time",
        "thread_time_ns",
        "tzset",
    },
    only_runtime=True,
),