Grades are a hygiene check, not a security guarantee.

Claude Code, Skill

Sansheng Write

Use when 用户要写、改、润色或排版中文长文和公众号文章,或明确要求把已发布文章转成小红书/微博图文、转成 X(Twitter)文章/发推特长文;触发对象为中文长文或公众号文章的创作、改稿、排版及按篇社媒分发(含 X 文章);普通短回复、代码/规则文档修改不触发。社媒分发按篇显式触发,不因拿到正式链接自动执行。AI 课程使用 sandy-class,晨报使用 sandy-morning-cards,视频使用 sansheng-video。

Compatibility: Not stated.

Grade B

Minor issues only, no Medium or High. Worth a quick look at the findings below before installing.

Graded by PlugVetRubric v2

Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.

PERMISSION_DELETE_FILES NETWORK_NO_FIXED_HOST NETWORK_UNNAMED_HOST SECRETS_PATH_DOTENV SECRETS_ENV_READ OBFUSCATION_FILE_OVER_READ_CAP OBFUSCATION_FILE_CAP_REACHED

Why this grade

  • PERMISSION_DELETE_FILES Low

    Contains a call that can delete files.

    scripts/audio_covers.py, line 437 completed = subprocess.run(

  • NETWORK_NO_FIXED_HOST Low

    Makes a network call whose host is not written as a fixed address.

    scripts/gen_img.py, line 137 为什么不再 subprocess 调 curl:以前 key 拼在 curl 的 argv(`-H "x-goog-api-key: ..."`),

  • NETWORK_UNNAMED_HOST Low

    Calls a fixed host that the description does not name.

    scripts/gen_img.py, line 137 为什么不再 subprocess 调 curl:以前 key 拼在 curl 的 argv(`-H "x-goog-api-key: ..."`),

  • SECRETS_PATH_DOTENV Low

    Mentions a .env file.

    conftest.py, line 7 # 测试必须确定性地跑在仓内 profile.example 上,且绝不受维护者本机 .env 影响

  • SECRETS_ENV_READ Note

    Reads an environment variable whose name contains KEY, SECRET, TOKEN, PASSWORD or CREDENTIAL.

    scripts/generate_article_bgm.py, line 179 env_tok = os.environ.get("GOOGLE_OAUTH_TOKEN", "").strip()

  • OBFUSCATION_FILE_OVER_READ_CAP Note

    A file was over the read cap and was not fully read.

    scripts/pipeline.py, line 1 #!/usr/bin/env python3

  • OBFUSCATION_FILE_CAP_REACHED Note

    The 400 file cap was reached before every file was read.

    scripts/pipeline.py, line 1 #!/usr/bin/env python3

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.

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

    scripts/audio_covers.py, line 437

    completed = subprocess.run(

    scripts/audio_covers.py, line 488

    done = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout,

    scripts/cover_blind_match.py, line 282

    completed = subprocess.run(

    Show more

    scripts/cover_blind_match.py, line 301

    shutil.rmtree(workdir, ignore_errors=True)

    scripts/cover_blind_match.py, line 352

    completed = subprocess.run(

    scripts/cover_blind_match.py, line 376

    shutil.rmtree(workdir, ignore_errors=True)

    scripts/cover_blind_match.py, line 583

    shutil.rmtree(workdir, ignore_errors=True)

    scripts/distribute.py, line 950

    2026-09-23 审计 D1:此前 subprocess.call 同步等待,而 weibo-post.ts 填好后因浏览器

    scripts/distribute.py, line 959

    proc = subprocess.Popen(argv, stdout=log, stderr=subprocess.STDOUT, start_new_session=True)

    scripts/flywheel_hooks.py, line 85

    out = subprocess.run([sys.executable, str(_learn_script()), "diff", "--draft", str(snap), "--final", str(final),

    scripts/format_layout.py, line 1386

    result = subprocess.run(

    scripts/handoff_assets.py, line 468

    shutil.rmtree(resolved)

    scripts/handoff_assets.py, line 533

    shutil.rmtree(temp)

    scripts/physical_archive.py, line 146

    shutil.rmtree(stage)

    scripts/physical_archive.py, line 278

    shutil.rmtree(source)

    scripts/transcribe_audio.py, line 260

    shutil.rmtree(workdir, ignore_errors=True)

  • Install and update

    Pass

    No install-time script found, and dependencies are pinned or absent.

  • Network

    Concern

    can reach a host that is not written as a fixed address. can reach mp.weixin.qq.com. The description does not name that host.

    NETWORK_NO_FIXED_HOST NETWORK_UNNAMED_HOST

    scripts/gen_img.py, line 137

    为什么不再 subprocess 调 curl:以前 key 拼在 curl 的 argv(`-H "x-goog-api-key: ..."`),

    scripts/gen_img.py, line 140

    (与原 `curl -s` 行为一致:Google/OpenAI 都用 JSON error 字段描述错误,交给上层统一报)。

    scripts/gen_img.py, line 149

    with urllib.request.urlopen(req, timeout=timeout) as r:

    Show more

    scripts/gen_img.py, line 274

    with urllib.request.urlopen(url, timeout=timeout) as r:

    scripts/generate_article_bgm.py, line 433

    with urllib.request.urlopen(req, timeout=900) as resp:

    scripts/recover_images_from_wechat.py, line 30

    def fetch(url: str, referer: str = "") -> bytes:

    scripts/recover_images_from_wechat.py, line 32

    return urllib.request.urlopen(req, timeout=40).read()

    scripts/recover_images_from_wechat.py, line 62

    html = fetch(url).decode("utf-8", "replace")

  • Secrets

    Concern

    reads a credential or environment file.

    SECRETS_ENV_READ SECRETS_PATH_DOTENV

    conftest.py, line 7

    # 测试必须确定性地跑在仓内 profile.example 上,且绝不受维护者本机 .env 影响

    conftest.py, line 8

    # - - .env 里的 SANSHENG_WRITE_PROFILE_DIR / SANSHENG_WRITE_DATA_DIR 会把 profile 指向

    scripts/generate_article_bgm.py, line 179

    env_tok = os.environ.get("GOOGLE_OAUTH_TOKEN", "").strip()

    Show more

    conftest.py, line 15

    # 同族指针一并钉死(.env 里它们可能直指真实作品库/私有飞轮 - - 测试绝不能碰)。

    conftest.py, line 16

    # ⚠ 必须钉**非空实路径**:空串挡不住解析器(os env 为空会继续回落 .env)。

    scripts/add_logo.js, line 100

    // 读仓根 .env 里的一个键(Node 进程看不见 .env - - Python 侧的 profile_config 才解析它。

    scripts/add_logo.js, line 105

    const envFile = path.resolve(__dirname, '../.env');

    scripts/add_logo.js, line 114

    } catch (e) { /* 无 .env = 正常路径,走回退 */ }

    scripts/add_logo.js, line 118

    // logo 目录来自你的 profile:优先 SANSHENG_WRITE_PROFILE_DIR(shell env → 仓根 .env)/brand,

    scripts/setup_check.py, line 190

    tok = os.environ.get("GOOGLE_OAUTH_TOKEN", "").strip() or _gc(

    scripts/visual_qa_openai.py, line 47

    key = os.getenv("SANSHENG_WRITE_VISUAL_QA_API_KEY") or os.getenv("OPENAI_API_KEY") or ""

    scripts/wechat_tunnel.py, line 31

    return {"host": host, "user": user or "root", "port": int(port or 22), "key": os.environ.get("SANSHENG_WRITE_WECHAT_TUNNEL_KEY", "").strip()}

  • Agent instructions

    Pass

    No instruction to ignore earlier instructions or to hide a step.

  • Obfuscation

    Note

    a file was over the read cap and was not fully read. the file cap was reached before every file was read.

    OBFUSCATION_FILE_OVER_READ_CAP OBFUSCATION_FILE_CAP_REACHED

    scripts/pipeline.py, line 1

    #!/usr/bin/env python3

    tests/test_x_article.py, line 1

    # -*- coding: utf-8 -*-

  • 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 8d5cdadd400e. can delete files. can reach a host that is not written as a fixed address. can reach mp.weixin.qq.com. The description does not name that host. reads a credential or environment file. a file was over the read cap and was not fully read. the file cap was reached before every file was read.

Date and source

Date checked:

View source

github.com

Commit graded: 8d5cdadd400e887e02bf6451caf383aac5bfb55f

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.

Read how this letter is chosen