Is Video Podcast Maker safe?
- Python shell/command execution
- Python filesystem write/delete
- Python filesystem read
repo is an AI ai_component analyzed by SkillTotal's deterministic static scanner. The scan found no malicious indicators, though 4 risky constructs are reported for review. It can: filesystem read, filesystem write, network egress and shell execution — capabilities are what the code can do, not a verdict on intent. Risk score 0/100 (low).
repo
Automated static-analysis result. It can contain false positives and false negatives, and is not a claim about the intent of Video Podcast Maker's authors. Report a false positive.
Behavioral traits
How this component maps to the CSA agentic threat model. Descriptive — it never affects the risk score.
Findings (4)
The component can run operating-system commands or spawn processes.
result = subprocess.run(
["ffprobe", "-v", "quiet", "-show_entries", "format=duration",
"-of", "csv=p=0", str(wav_path)],
capture_output=True, text=True, check=True,
)return subprocess.run(cmd).returncode
out = subprocess.check_output(["node", "--version"], text=True, timeout=10)
result = subprocess.run(cmd, capture_output=True, text=True)
result = subprocess.run(cmd, capture_output=True, text=True)
concat_result = subprocess.run(
["ffmpeg", "-y", "-f", "concat", "-safe", "0",
"-i", os.path.basename(concat_list), "-c", "copy",
os.path.basename(output_wav)],
capture_output=True, text=True, cwd=args.outp …result = subprocess.run(
[
"ffprobe",
"-v",
"error",
"-show_entries",
"format=duration",
"-of",
"default=noprint_wra …result = subprocess.run(
[
"ffprobe",
"-v",
"error",
"-select_streams",
"v:0",
"-show_entries",
"stream=width,height …subprocess.run(cmd, capture_output=True, text=True, check=True)
probe = subprocess.run(
["ffprobe", "-v", "quiet", "-show_entries", "format=duration", "-of", "csv=p=0", part_file],
capture_output=True, text=True)proc = subprocess.run(cmd, capture_output=True, text=True, env=sub_env)
resample = subprocess.run(
["ffmpeg", "-y", "-i", raw_file, "-ar", "48000", "-ac", "1", part_file],
capture_output=True, text=True)result = subprocess.run(
['ffprobe', '-v', 'quiet', '-show_entries', 'format=duration',
'-of', 'csv=p=0', wav_path],
capture_output=True, text=True, check=True)out = subprocess.check_output(
[
"ffprobe",
"-v",
"quiet",
"-print_format",
"json",
"-show_streams",
"-show_format", …out = subprocess.check_output(
[
"ffprobe",
"-v",
"quiet",
"-print_format",
"json",
"-show_streams",
"-show_format", …Why it matters: Powerful and often legitimate — confirm the commands aren't built from untrusted input.
Fix: Confirm the command and its arguments are fully controlled and not derived from untrusted input; avoid shell=True.
The component reads files from disk.
text = path.read_text(encoding="utf-8")
text = path.read_text(encoding="utf-8")
timing = json.loads(timing_path.read_text(encoding="utf-8"))
json.dumps(json.loads(timing_path.read_text(encoding="utf-8")), indent=2, ensure_ascii=False),
with open(path, encoding="utf-8") as f:
tsx_text = open(tsx_path, 'r', encoding='utf-8').read()
timing = json.loads(open(timing_path, 'r', encoding='utf-8').read())
srt_text = open(srt_path, 'r', encoding='utf-8').read()
text = filepath.read_text(encoding="utf-8")
1 for f in files if pattern.search(f.read_text(encoding="utf-8"))
with open(path, 'r', encoding='utf-8') as f:
with open(path, 'r', encoding='utf-8') as f:
with open(args.input, "r", encoding="utf-8") as f:
with open(report_path, encoding="utf-8") as f:
with open(template_path, encoding="utf-8") as f:
with open(prefs_path, encoding="utf-8") as f:
with open(prefs_path, encoding="utf-8") as f:
with open(prefs_path) as f:
with open(template_path, "r", encoding="utf-8") as f:
with open(template_path, "r", encoding="utf-8") as f:
with open(global_path, "r", encoding="utf-8") as f:
with open(global_path, "r", encoding="utf-8") as f:
with open(override_path, "r", encoding="utf-8") as f:
with open(timing_path, 'r', encoding='utf-8') as f:
with open(prefs_path, encoding="utf-8") as f:
Why it matters: Usually legitimate, but worth confirming it can't be steered into reading sensitive files.
Fix: Confirm which files are read and that paths cannot be influenced by untrusted input to reach sensitive locations.
The component writes or deletes files on disk.
shutil.copy2(src, tmp)
backup_path.write_text(
json.dumps(json.loads(timing_path.read_text(encoding="utf-8")), indent=2, ensure_ascii=False),
encoding="utf-8",
)timing_path.write_text(json.dumps(timing, indent=2, ensure_ascii=False), encoding="utf-8")
with open(path, "w", encoding="utf-8") as f:
shutil.copy2(src, dest)
with open(path, 'w', encoding='utf-8') as f:
with open(info_path, 'w', encoding='utf-8') as f:
with open(snippet_path, 'w', encoding='utf-8') as f:
with open(phonemes_path, "w", encoding="utf-8") as f:
with open(concat_list, "w", encoding="utf-8") as f:
shutil.copy2(src, dest)
shutil.copy2(src, cover_dest)
shutil.copy2(frames[0], os.path.join(ref_dir, "cover.jpg"))
with open(report_path, "w", encoding="utf-8") as f:
os.unlink(tmp_path)
shutil.rmtree(ref_dir)
shutil.rmtree(ref_dir, ignore_errors=True)
os.remove(raw_file)
os.unlink(tmp_path)
with open(output_path, "w", encoding="utf-8") as f:
with open(output_path, "w", encoding="utf-8") as f:
with open(timing_path, 'w', encoding='utf-8') as f:
shutil.copy2(bgm_mp4, final_mp4)
shutil.copy2(output_mp4, final_mp4)
Why it matters: Usually legitimate, but worth confirming the paths can't be controlled by untrusted input.
Fix: Confirm which files are written/deleted and that paths cannot be influenced by untrusted input.
The component makes outbound network requests.
const response = await fetch(url);
Why it matters: Usually legitimate, but confirm the destinations are expected and no sensitive data leaves.
Fix: Confirm the destination hosts are expected and that no sensitive data is sent off-host.
Check your own component
Run the same evidence-backed scan on any MCP server, agent skill, or package.
Scan your own componentHow we determine this: deterministic static analysis (regex + AST), evidence-anchored, no code execution. Methodology →