TavernKeeper Scan Report

vegu-ai/talemate

Commit cc28def Reviewed

No material or immediate-danger concern was identified in this review.

This advisory report describes what the named tools and review process found at one exact commit. Unknown or unobserved behavior may still exist.

0 immediate danger 0 material 34 low

What this review found

No material or immediate-danger item was identified.

Deterministic technical evidence (24)
  • zizmor reported artipacked · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:20

  • zizmor reported cache-poisoning · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:70

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:67

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/test.yml:32

  • Dependency advisory GHSA-r28c-9q8g-f849:pkg:29462f87d245964d2c009cb3 applies · osv-scanner 2.4.0

    A dependency has a published security issue, though this scan does not show that the project exposes it to an attacker.

    Policy reason: osv-structured-advisory · Execution scope: unknown

    Source: talemate_frontend/pnpm-lock.yaml

  • zizmor reported artipacked · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:62

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:42

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/test-container-build.yml:37

  • zizmor reported excessive-permissions · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/test.yml:10-62

  • Dependency advisory GHSA-fxqj-rqcc-2cmp:pkg:aca07d40b95977daa7f2c14c applies · osv-scanner 2.4.0

    A dependency has a published security issue, though this scan does not show that the project exposes it to an attacker.

    Policy reason: osv-structured-advisory · Execution scope: unknown

    Source: talemate_frontend/pnpm-lock.yaml

  • Dependency advisory GHSA-2v37-7h3g-55p8:pkg:32565e5915130b51271b4195 applies · osv-scanner 2.4.0

    A dependency has a published security issue, though this scan does not show that the project exposes it to an attacker.

    Policy reason: osv-structured-advisory · Execution scope: unknown

    Source: talemate_frontend/pnpm-lock.yaml

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/test.yml:18

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/test-container-build.yml:44

  • zizmor reported artipacked · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/test-container-build.yml:15

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:62

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/test-container-build.yml:15

  • zizmor reported artipacked · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/test.yml:18

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:70

  • Dependency advisory GHSA-28wg-ghj8-5hjv:pkg:d681b9f3617b82bd6b835445 applies · osv-scanner 2.4.0

    A dependency has a published security issue, though this scan does not show that the project exposes it to an attacker.

    Policy reason: osv-structured-advisory · Execution scope: unknown

    Source: talemate_frontend/pnpm-lock.yaml

  • zizmor reported excessive-permissions · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:13

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/test.yml:21

  • zizmor reported excessive-permissions · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:12

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:49

  • zizmor reported unpinned-uses · zizmor 1.28.0

    The code has a known weakness, though this scan does not show that anyone can exploit it here.

    Policy reason: zizmor-known-workflow-rule · Execution scope: automation

    Source: .github/workflows/ci.yml:20

Contextual expected matches (7)

JavaScript analysis reported javascript.xray.unsafe-regex

Expected behavior · high confidence

A scanner flagged a regular expression used to validate hex color values as potentially unsafe. The regex is simple and bounded with no risk of performance issues. It is used to check whether a color widget value is a valid hex color like #RRGGBB.

Technical evidence

Scanner reason: JavaScript analysis matched static JavaScript security signal javascript.xray.unsafe-regex. The match applies to this repository.

Contextual assessment: Line 340 contains the regex /^#[0-9a-fA-F]{6}([0-9a-fA-F]{2})?$/ used in a .test() call to validate whether a widget value is a valid hex color string. This regex is fully anchored (^ and $), uses fixed quantifiers ({6}, {2}), has no nested quantifiers, and no alternation that could cause catastrophic backtracking. The input (widget.value) is a local UI property, not network-supplied. The regex is not vulnerable to ReDoS. The scanner flag is a false positive on a simple, safe validation pattern.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
javascript-analysis webcrack-2.16.0_js-x-ray-16.0.0_signatures-1_literals-1_families-1
Rule
javascript.xray.unsafe-regex
File role
production
Source
talemate_frontend/src/utils/litegraphUtils.js:340

OpenGrep reported tavernkeeper.dynamic-execution.python-eval-or-shell

Expected behavior · high confidence

The code simply clears the terminal screen using either the 'cls' or 'clear' command depending on the operating system. No user input is involved, and the commands are hardcoded. This is completely harmless.

Technical evidence

Scanner reason: OpenGrep matched static-analysis rule tavernkeeper.dynamic-execution.python-eval-or-shell. The match applies to this repository.

Contextual assessment: Line 345 calls os.system with a hardcoded string: 'cls' on Windows (os.name == 'nt') or 'clear' on other platforms. Neither string contains user-controlled input or variable interpolation. The command solely clears the terminal display before printing startup text. There is no injection vector since the argument is a compile-time constant selected by the platform check. This is a benign UI utility call.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
opengrep 1.26.0
Rule
tavernkeeper.dynamic-execution.python-eval-or-shell
File role
production
Source
src/talemate/server/run.py:345

JavaScript analysis reported javascript.xray.unsafe-regex

Expected behavior · high confidence

The flagged regular expression is a standard pattern for parsing ISO-8601 duration strings (like PT30M or P3D). It is anchored, uses simple non-overlapping digit groups, and does not create any risk of denial-of-service or other harm. The scanner signal is a false positive.

Technical evidence

Scanner reason: JavaScript analysis matched static JavaScript security signal javascript.xray.unsafe-regex. The match applies to this repository.

Contextual assessment: The regex on line 10 parses ISO-8601 duration strings. It is anchored with ^ and $, and each optional component uses a single (?:...) group containing (digit-group). There are no nested quantifiers, no overlapping alternations, and no backtracking-prone constructs that could cause catastrophic backtracking (ReDoS). The input is matched once per call with a bounded, linear pattern. No data exfiltration, execution, or persistence is involved. The scanner's unsafe-regex signal is a false positive on this straightforward duration parser.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
javascript-analysis webcrack-2.16.0_js-x-ray-16.0.0_signatures-1_literals-1_families-1
Rule
javascript.xray.unsafe-regex
File role
production
Source
talemate_frontend/src/utils/time.js:10

OpenGrep reported tavernkeeper.dynamic-execution.python-eval-or-shell

Expected behavior · high confidence

The project runs scenario-specific Python scripts using RestrictedPython, a library designed to limit what code can do. This is an intended feature for the roleplay platform's advanced scenario scripting. The scripts come from the user's own local scene files.

Technical evidence

Scanner reason: OpenGrep matched static-analysis rule tavernkeeper.dynamic-execution.python-eval-or-shell. The match applies to this repository.

Contextual assessment: The exec_restricted function at line 47 uses RestrictedPython's compile_restricted to compile code before executing it with exec. The globals dictionary is populated with safe_globals, guarded iterators (default_guarded_getiter, default_guarded_getitem), safer_getattr, and a restricted _write_ policy. This is the intended use of RestrictedPython as a sandbox for executing user-authored scene modules (game.py) that provide gameplay hooks. The code source is local scene files on disk, not network input. RestrictedPython is specifically designed for this use case.

Impact: low · Exploitability: unlikely

Developer action: none

Scanner
opengrep 1.26.0
Rule
tavernkeeper.dynamic-execution.python-eval-or-shell
File role
production
Source
src/talemate/game/engine/__init__.py:47

OpenGrep reported tavernkeeper.dynamic-execution.python-eval-or-shell

Expected behavior · high confidence

This second exec call uses the same RestrictedPython sandbox as the first. It compiles and runs scene module code with the same safety guards in place. This is the expected behavior for the scenario scripting feature.

Technical evidence

Scanner reason: OpenGrep matched static-analysis rule tavernkeeper.dynamic-execution.python-eval-or-shell. The match applies to this repository.

Contextual assessment: The compile_scene_module function at line 73 uses the same RestrictedPython compile_restricted and safe_globals pattern as exec_restricted. It compiles scene module code with identical guards (default_guarded_getiter, default_guarded_getitem, safer_getattr, guarded_iter_unpack_sequence) before executing. The module code is read from a local game.py file in the scene's save directory (line 186-187), representing user-authored scenario logic. The function returns only the 'game' and 'on_generation_cancelled' callables from the executed module, limiting exposure.

Impact: low · Exploitability: unlikely

Developer action: none

Scanner
opengrep 1.26.0
Rule
tavernkeeper.dynamic-execution.python-eval-or-shell
File role
production
Source
src/talemate/game/engine/__init__.py:73

malcontent reported anti-static-xor-terms

Expected behavior · medium confidence

A scanner flagged a logo image file for containing obfuscated data. However, this is a PNG image file whose binary contents were not provided for review. Image files naturally contain compressed binary data that can trigger false positives in binary scanners. No malicious behavior is demonstrated.

Technical evidence

Scanner reason: malcontent matched behavioral-analysis rule anti-static-xor-terms. The match applies to this repository.

Contextual assessment: The scanner flagged a PNG logo file with an XOR obfuscation rule, but this is a metadata-only assessment where the artifact bytes were not supplied. PNG files contain compressed pixel data and metadata chunks that can produce byte patterns matching XOR-related heuristics in binary analysis tools. The file is a static image asset in the frontend assets directory, not an executable. Without the raw artifact contents, no actual obfuscation, code execution, or data exfiltration can be demonstrated. Metadata-only evidence cannot support material or high risk per review policy.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
malcontent 1.25.7
Rule
anti-static-xor-terms
File role
production
Source
talemate_frontend/src/assets/logo-11-final.png

OpenGrep reported tavernkeeper.download-and-execute.shell-pipeline

Expected behavior · high confidence

The installer script downloads Python and Node.js from their official websites and saves them as zip files on disk. It does not pipe or execute downloaded content directly. This is a standard, safe installer pattern.

Technical evidence

Scanner reason: OpenGrep matched static-analysis rule tavernkeeper.download-and-execute.shell-pipeline. The match applies to this repository.

Contextual assessment: The scanner flagged curl usage on line 107, but the command `curl -L -# -o %PY_ZIP% %PY_URL%` downloads a Python embedded zip from python.org to a local file. The downloaded archive is then extracted via tar and verified by checking for python.exe existence before use. The URLs are hardcoded to official python.org and nodejs.org distribution endpoints, not user-controlled. No downloaded content is piped into a shell or executed immediately; the archive is saved, extracted, and the extracted python.exe is invoked as an interpreter. This matches the stated installer purpose and does not constitute download-and-execute.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
opengrep 1.26.0
Rule
tavernkeeper.download-and-execute.shell-pipeline
File role
production
Source
install.bat:107

Related contextual observations

Node.js download follows same safe save-then-extract pattern

low risk · high confidence

The Node.js download on line 185 uses the same safe pattern as the Python download: save to a zip file, extract with tar, verify node.exe exists before use.

Technical assessment

The Node.js download at line 185 follows the identical pattern: curl saves to a local zip, tar extracts it, and node.exe existence is verified. No download-and-execute pattern exists here either.

Impact: none · Exploitability: unlikely

Developer action: none

Sources:

Scene modules loaded from local files with RestrictedPython sandbox

low risk · medium confidence

Scene files can be shared between users. If someone shares a scene with a malicious game.py, the RestrictedPython sandbox may not block all attacks. Users should be cautious when importing scenes from untrusted sources.

Technical assessment

Scene modules are loaded from local files (game.py in scene save_dir). If scenes can be imported or shared, a malicious game.py could be included. While RestrictedPython provides significant restrictions, it is not a formal security sandbox and has known bypass techniques in some configurations. The _write_ guard is set to a passthrough lambda, which could allow writes to mutable objects. This is a defense-in-depth consideration but not a demonstrated vulnerability since no attacker-controlled input path to the exec calls is shown in the supplied evidence.

Impact: low · Exploitability: unlikely

Developer action: Document that scene game.py files execute in a RestrictedPython sandbox and may not be fully safe to load from untrusted sources.

Sources:

ISO-8601 duration regex is linear and safe

low risk · high confidence

The regex is a simple, well-structured ISO-8601 duration parser with no risk of catastrophic backtracking.

Technical assessment

The regex /^P(?:(digit-group)Y)?(?:(digit-group)M)?...$/ is a linear, anchored pattern with independent optional groups. Each group matches at most one run of digits and there is no ambiguity or nested repetition that could cause exponential backtracking. This is a safe, standard ISO-8601 duration parsing approach.

Impact: none · Exploitability: unlikely

Developer action: none

Sources:

Coverage and limitations

JavaScript coverage

Tools

Limitations

Technical scan identity