os.system(f"manimgl {__file__} ClassName") interpolates the script's own
path into a shell string. These templates are meant to be copied and
renamed per-scene by an agent, so a scene/folder name containing shell
metacharacters is a real injection path, not just malformed input.
Switched to subprocess.run() with an argument list (no shell=True), so
there's nothing left for a shell to interpret regardless of what the
path contains. Same fix applied in both duplicate locations
(.claude/skills and .agents/skills) since the files are identical.
Reviewed scripts/lib/tts.mjs's child_process usage as part of the same
report -- not included in this PR, it already passes args as a real
array with no shell:true anywhere in the call chain, so it isn't
actually exploitable.