Claude Code, Skill
Video Production Skills
Fifteen agent skills, two host-side tools and a look library for producing video: short-form ad campaigns, short films and music videos made from generated footage or from a client's own clips, and narrated motion-graphics explainers drawn in code.
Compatibility: Not stated.
Grade D
Two or more Medium findings, or a High. Only try it in a sandbox.
Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.
NETWORK_HOST_FROM_INPUT OBFUSCATION_ENCODED_BLOB
Why this grade
- NETWORK_HOST_FROM_INPUT Medium
A file takes a URL or endpoint as input and has no fixed host list.
skills/spot-audio-assembly/scripts/gen_vo.py, line 37
def get(url): return json.load(urllib.request.urlopen(urllib.request.Request(url, headers=H), timeout=30)) - OBFUSCATION_ENCODED_BLOB Medium
Contains a long base64 shaped string in a file that should be readable.
look-library/cubes/ads-clean_33.cube, line 1
TITLE "look-library ads-clean (ads)"
Any High, or two or more Medium findings, give D. One Medium gives C. Low findings or a security Note give B. Each code names a finding behind the letter.
If you think this grade is wrong, email [email protected] with the entry link and your evidence. We aim to acknowledge within two working days and decide within seven. If we confirm an error, we aim to correct it within 24 hours of confirming it. These are aims, not guarantees.
Grades are a hygiene check of the source at the commit shown, on the date checked, not a security audit or a guarantee. The free directory grades are automated. Before release, a PlugVet engineer reviews every paid report and any grade we hold back, including all F grades, against the source code and the evidence we quote.
What was checked
Plain notes from the hygiene checks.
Permissions
Concern
can delete files.
PERMISSION_DELETE_FILES
look-library/preview.py, line 20
r = subprocess.run(cmd, capture_output=True, text=True)
skills/ad-spot-preprod/scripts/reference_teardown.py, line 32
return subprocess.run(cmd, capture_output=True, check=True, **kw)
skills/ad-spot-preprod/scripts/reference_teardown.py, line 53
p = subprocess.Popen(['ffmpeg', '-v', 'error', '-i', path, '-vf', vf, '-f', 'rawvideo', '-'], stdout=subprocess.PIPE)
Show more
skills/ad-spot-preprod/scripts/reference_teardown.py, line 154
e = subprocess.run(['ffmpeg', '-hide_banner', '-i', path, '-af', 'ebur128', '-f', 'null', '-'], capture_output=True, text=True).stderr
skills/ad-spot-preprod/scripts/reference_teardown.py, line 293
p = subprocess.Popen(['ffmpeg', '-v', 'error', '-y', '-f', 'rawvideo', '-pix_fmt', 'gray', '-s', f'{W}x{H}', '-r', str(fps), '-i', '-',
skills/ad-spot-preprod/scripts/reference_teardown.py, line 302
shutil.rmtree(d, ignore_errors=True)
skills/client-rounds/scripts/compare_versions.py, line 30
r = subprocess.run(['ffprobe', '-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=width,height,r_frame_rate:format=duration',
skills/client-rounds/scripts/compare_versions.py, line 300
subprocess.run(['ffmpeg', '-v', 'error', '-nostdin', '-f', 'lavfi', '-i', f'testsrc2=size=96x170:rate=24:duration={s}', '-c:v', 'libx264', '-pix_fmt', 'yuv420p',
skills/client-rounds/scripts/compare_versions.py, line 309
again = subprocess.run([sys.executable, os.path.abspath(__file
skills/client-rounds/scripts/compare_versions.py, line 318
shutil.rmtree(d, ignore_errors=True)
skills/client-rounds/scripts/delivery_ask.py, line 216
shutil.rmtree(d, ignore_errors=True)
skills/video-edit-edl/scripts/av_sync_regress.py, line 196
if not a.keep: shutil.rmtree(root, ignore_errors=True)
skills/video-edit-edl/scripts/edge_audit.py, line 377
os.remove(sil)
skills/video-edit-edl/scripts/edge_audit.py, line 378
for k in ('take.wav', 'deliv.wav'): os.remove(os.path.join(d, k))
skills/video-finish/scripts/phone_native.py, line 128
os.remove(cmdfile)
skills/video-finish/scripts/phone_native.py, line 132
os.remove(cmdfile)
Install and update
Pass
No install-time script found, and dependencies are pinned or absent.
Network
Serious
accepts a host from input, with no fixed list in this file.
NETWORK_HOST_FROM_INPUT
skills/spot-audio-assembly/scripts/gen_vo.py, line 37
def get(url): return json.load(urllib.request.urlopen(urllib.request.Request(url, headers=H), timeout=30))
skills/spot-audio-assembly/scripts/gen_vo.py, line 56
try: print('added shared voice', j.get('label'), json.load(urllib.request.urlopen(req, timeout=30)).get('voice_id')); mine.add(vid)
skills/spot-audio-assembly/scripts/gen_vo.py, line 68
with urllib.request.urlopen(req, timeout=90) as r: data = r.read()
Show more
skills/spot-audio-assembly/scripts/vo_word_times.py, line 53
with urllib.request.urlopen(req, timeout=120) as r: o = json.load(r)
skills/video-finish-qc/scripts/upscale_fal_topaz.py, line 47
with urllib.request.urlopen(r, timeout=timeout) as resp:
skills/video-finish-qc/scripts/upscale_fal_topaz.py, line 67
with urllib.request.urlopen(r, timeout=600) as resp: resp.read()
skills/video-gen-cost-gate/scripts/gen_stills.py, line 45
d = json.loads(urllib.request.urlopen(req, timeout=120).read())
skills/video-gen-cost-gate/scripts/gen_stills.py, line 56
s = json.loads(urllib.request.urlopen(rq, timeout=60).read())
skills/video-gen-cost-gate/scripts/monid_upload.py, line 34
And two wire rules that fail silently if broken: the bytes go by RAW PUT (`curl -T`), never multipart
Secrets
Concern
reads a credential or environment file.
SECRETS_ENV_READ SECRETS_PATH_DOTENV
AGENTS.md, line 42
cp .env.example .env # fill in only the vendors you use
AGENTS.md, line 43
set -a; . ~/.claude/skills/video-production/../../.env; set +a # load in the command that needs it
install.sh, line 18
environment variable; the optional overrides are listed in .env.example and tools/README.md.
Show more
install.sh, line 19
Keys: copy .env.example to .env, fill in the vendors you use, and load it in the command that needs it:
install.sh, line 20
set -a; . ~/.claude/skills/video-production/../../.env; set +a
skills/spot-audio-assembly/scripts/gen_vo.py, line 35
key = os.environ.get('ELEVENLABS_API_KEY'); H = {'xi-api-key': key or '', 'Content-Type': 'application/json'}
skills/spot-audio-assembly/scripts/vo_word_times.py, line 71
key = os.environ.get('ELEVENLABS_API_KEY')
skills/video-finish-qc/scripts/upscale_fal_topaz.py, line 38
key = os.environ.get('FAL_KEY')
skills/video-gen-cost-gate/scripts/gen_stills.py, line 144
key = os.environ.get("KIE_API_KEY", "").strip()
skills/video-gen-cost-gate/scripts/gen_video_fal.py, line 87
k = os.environ.get("FAL_KEY", "").strip().strip("\"'")
skills/video-gen-cost-gate/scripts/gen_video_kie.py, line 309
api_key = os.environ.get('KIE_API_KEY', '').strip()
skills/video-gen-cost-gate/scripts/hf_api.py, line 95
kid = (os.environ.get('HF_API_KEY_ID') or '').strip()
skills/video-gen-cost-gate/scripts/hf_api.py, line 96
sec = (os.environ.get('HF_API_KEY_SECRET') or '').strip()
.env.example, line 1
# Copy this file to .env (gitignored) and fill in the keys for the parts of the kit you use. The scripts read keys
.env.example, line 2
# from the process environment, never from this file, so load .env in the same command that needs it:
.env.example, line 3
# set -a; . ~/.claude/skills/video-production/../../.env; set +a
Agent instructions
Pass
No instruction to ignore earlier instructions or to hide a step.
Obfuscation
Concern
contains an encoded blob in a file that should be readable.
OBFUSCATION_ENCODED_BLOB
look-library/cubes/ads-clean_33.cube, line 1
TITLE "look-library ads-clean (ads)"
look-library/cubes/ads-warm_33.cube, line 1
TITLE "look-library ads-warm (ads)"
look-library/cubes/film-cinestill_33.cube, line 1
TITLE "look-library film-cinestill (film)"
Show more
look-library/cubes/film-portra_33.cube, line 1
TITLE "look-library film-portra (film)"
look-library/cubes/film-teal-orange_33.cube, line 1
TITLE "look-library film-teal-orange (film)"
look-library/cubes/ugc-phone_33.cube, line 1
TITLE "look-library ugc-phone (ads)"
look-library/drx/ads-clean.drx, line 4
<FieldsBlob>00000001000000040000001c004d0065006400690061004600720061006d006500520061007400650000000c0000000010000000000000384000000000000000000000002e004700720061007000680054006800
look-library/drx/ads-clean.drx, line 28
<Body>8128b52ffd600004851b00f631b64ae0d2b801200846c3192290edf3218f097491778e89235718a3d67fbc0977884cf34aae43b689e464c22109849929f178772d2f66b3282d372f383baef189c0fe5da7c17e4ae0514b
look-library/drx/ads-clean.drx, line 42
<Body>8128b52ffd20642103000a4008ffffffff0f10011a1e08b80810800f1d0000803f20b80828800f350000803f38b80840800f48012080c60a4a0408021040520408031040580160d499b3f7491a2020be0128b401380140
look-library/drx/ads-clean.drx, line 52
<Buffer>ffd8ffe000104a46494600010101006000600000ffdb004300080606070605080707070909080a0c140d0c0b0b0c1912130f141d1a1f1e1d1a1c1c20242e2720222c231c1c2837292c30313434341f27393d38323c2e
look-library/drx/ads-clean.drx, line 55
<ClipThumbnails>0adf14080212da1408b801105c180122d014ffd8ffe000104a46494600010101006000600000ffdb004300080606070605080707070909080a0c140d0c0b0b0c1912130f141d1a1f1e1d1a1c1c20242e2720
look-library/drx/ads-warm.drx, line 4
<FieldsBlob>00000001000000040000001c004d0065006400690061004600720061006d006500520061007400650000000c0000000010000000000000384000000000000000000000002e004700720061007000680054006800
look-library/drx/ads-warm.drx, line 28
<Body>8128b52ffd601d04351c009633bb49e0b4b801685aca3a000524e3325de9c3b8b44a2870f430bee82bf93ad2be255248ae6fa4c4929214242079ad3b9448c6187b8049cff2080aa6836bc26705b2915328375222cf5fd2
look-library/drx/ads-warm.drx, line 42
<Body>8128b52ffd20642103000a4008ffffffff0f10011a1e08b80810800f1d0000803f20b80828800f350000803f38b80840800f48012080c60a4a0408021040520408031040580160bab1e9894b1a2020be0128b401380140
Licence
Pass
A licence file is present (LICENSE).
Maintainer activity
Pass
The latest commit is within the last 365 days.
Note
Hygiene check of commit 25495590b28e. can delete files. accepts a host from input, with no fixed list in this file. reads a credential or environment file. contains an encoded blob in a file that should be readable.
Date and source
Date checked:
github.com
Commit graded: 25495590b28e0f33057d2869264975ddf063c0af
This link goes to the original host. PlugVet does not host or check what you download from there, and installing it is your own decision and risk.