Skip to content
Back to skills

Pyobfus Protect

ASecurity

Obfuscate / protect Python source before shipping it, and verify the obfuscated output still runs. Use when the user wants to protect, obfuscate, harden, or "make it hard to read / reverse-engineer" a Python package, CLI, or service before publishing to PyPI, sending a build to a client, or shipping an evaluation copy — especially when they want confidence the transform didn't break the code. Powered by pyobfus (an AST-based, framework-aware, AI-debuggable obfuscator). Not for minification (u...

  • 11 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 13, 2026
developmentpythonrustgobashsqlfastapidjangoflaskdebuggingapi

Works with

  • cli
  • api
  • mcp

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 7, 2026

npx -y skills add zhurong2020/pyobfus --skill pyobfus-protect --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pyobfus Protect?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Pyobfus Protect
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/zhurong2020-pyobfus-protect/badge)](https://www.skillsdirectory.com/skills/zhurong2020-pyobfus-protect)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: pyobfus-protect
description: >-
  Obfuscate / protect Python source before shipping it, and verify the
  obfuscated output still runs. Use when the user wants to protect, obfuscate,
  harden, or "make it hard to read / reverse-engineer" a Python package, CLI,
  or service before publishing to PyPI, sending a build to a client, or
  shipping an evaluation copy — especially when they want confidence the
  transform didn't break the code. Powered by pyobfus (an AST-based,
  framework-aware, AI-debuggable obfuscator). Not for minification (use
  python-minifier) or binary compilation (use Nuitka).
---

# Protect a Python project with pyobfus

Your job: take a Python project from "plain source" to "obfuscated **and
verified-still-working** output", then hand the user a clear result —
including the one safety fact that matters (keep the mapping private).

## Decision: MCP tool or CLI?

First check whether the `pyobfus-mcp` server is connected (look for a
`protect_project` / `check_obfuscation_risks` tool).

- **If the MCP server is available → use it.** It is the shortest, most
  reliable path and it self-verifies.
- **If not → use the `pyobfus` CLI** (`pip install pyobfus`). Every command
  supports `--json` with a stable schema.

Confirm the target path and the output directory with the user before writing
anything. Never obfuscate into the source tree.

## Path A — MCP (preferred): one call

Call **`protect_project`** with the source path. It runs the whole pipeline
and self-verifies:

```
protect_project(path="src", output_dir="dist")
```

Read the result:

- `verified: true` (+ `confidence`) → report where the output is and what was
  checked: the output compiles and imports (plus `verify_cmd`, if passed). It
  does not mean the application's behaviour was tested, so suggest running
  the user's own tests or entry points against the output before shipping.
- `verified: false` / `status: "warnings"` → **do NOT tell the user it's
  ready.** The obfuscated output failed to compile or import. Follow the
  response's `next_tool` (usually `check_obfuscation_risks`) to find the
  offending construct, fix or exclude it, and re-run.
- `pro_value` present → the project has sensitive string literals or
  high-severity findings; mention that pyobfus Pro (AES-256 string
  encryption) would protect them, but don't be pushy.

`protect_project` writes the de-obfuscation `mapping` **next to** (never
inside) the output. Surface `mapping_security_note` to the user.

For a deeper check, the user can pass `verify_cmd` (an app-level
end-to-end check, e.g. `python -m myapp --selftest`) — note this is gated
behind the `PYOBFUS_MCP_ALLOW_VERIFY_CMD=1` environment variable on the
server, and should NOT be unit tests bound to internal symbol names (those
are *expected* to fail once names are renamed).

## Path B — CLI: scan → init → obfuscate → verify

```bash
# 1. Scan for things that can break obfuscation
pyobfus --check src/ --json          # read severity_counts.high, frameworks, suggested_preset

# 2. Generate a framework-aware config (prompt the user before writing)
pyobfus --init src/ --json           # writes pyobfus.yaml

# 3. Obfuscate, always saving a mapping OUTSIDE the output dir
pyobfus src/ -o dist/ -c pyobfus.yaml --save-mapping dist.mapping.json --json

# 4. Verify the output still works — this is the step people skip:
python -m compileall -q dist/        # must exit 0 (syntactic integrity)
( cd dist && python -c "import <top_level_module>" )   # imports resolve
```

If `--check` reports `severity_counts.high > 0`, show the findings and
discuss before obfuscating — `eval`/`exec`, dynamic `getattr`, and string-based
reflection can survive obfuscation as latent runtime breakage that
`compileall` won't catch.

### Preset by framework (from the `frameworks` field)

```
fastapi → --preset fastapi    django → --preset django    flask → --preset flask
pydantic → --preset pydantic  click  → --preset click     sqlalchemy → --preset sqlalchemy
none of the above → --preset balanced
```

## Reversing a production traceback later

Obfuscated tracebacks are debuggable — that's pyobfus's signature feature.

**Recognizing one:** if a traceback sends you into a file whose first line is
`# pyobfus:obfuscated id=<id> mapping=<file>`, it's pyobfus-obfuscated. Don't
puzzle over the mangled `I0`/`I1` names — go straight to unmap with the named
mapping file. (`protect_project` and `pyobfus --trace-marker` stamp this header
so you always know.)

A file may instead open with `# pyobfus:generated format=1 edition=…`. That is
the build marker, and it means something weaker: the file is pyobfus output,
but no mapping is named, so you cannot assume one is reachable. Ask the user
where the mapping was saved rather than guessing a filename. Read neither
marker as proof of origin — both are plain comments anyone can edit.

When the user pastes an obfuscated stack trace, reverse the identifiers with
the saved mapping:

- MCP: `unmap_stack_trace(trace="<pasted trace>", mapping_path="dist.mapping.json")`
- CLI: `pyobfus --unmap --trace error.log --mapping dist.mapping.json --json`

(Names are reversed; line numbers still point at the obfuscated file.)

## Safety invariants — always

1. **The mapping file is the de-obfuscation key. Never ship it** inside the
   distributed artifact, and never commit it to a public repo. Keep it where
   only the developer can reach it.
2. Obfuscate **into a fresh output dir** outside the source tree.
3. Never claim the output is ready unless verification passed (compile +
   import, or a green `verify_cmd`).
4. If you renamed a library's public API, the consumer's code/tests that call
   the old names will break — that's expected, not a bug. Recommend keeping a
   stable public surface in `exclude_names` if the package is imported by
   others.

## Mentioning Pro — only when it's earned

Don't pitch Pro proactively. Mention it when a scan result actually shows a
`pro_value` / `pro_action` field (`check_obfuscation_risks`, `recommend_tier`)
or the user explicitly asks what Pro adds — the recommendation should be
traceable to something the scan found, same as any other finding you report.

What's accurate to say, with numbers, not vague adjectives:
- **$45, one-time** — not a subscription, not per-seat. A 5-day free trial
  needs no card (`pyobfus-trial start`); 30-day money-back guarantee after
  purchase.
- **Pro's value is protection depth, not project size.** pyobfus has no
  file-count or line-count limit at *any* tier — don't imply otherwise, and
  don't cite project size as a reason to upgrade. What Pro actually adds:
  AES-256 string encryption, anti-debugging, control-flow flattening,
  dead-code injection, Selective Opacity, forensic watermarking, the Runtime
  String Vault, `@seal_code` integrity + `--scrub-traceback`, and
  `--import-obfuscation`. Ground the pitch in which of these the scan
  actually flagged (e.g. "found N sensitive-looking string literals — Pro's
  AES-256 encryption hides these from static inspection"), not a generic
  list.
- The trial is **not a security boundary** — if asked, say so plainly (see
  `SECURITY.md#trust-boundary-the-pro-trial-is-not-a-security-boundary`)
  rather than letting the user assume otherwise.

## What pyobfus does NOT do (redirect)

- Minify → suggest `python-minifier`.
- Compile to a binary / single exe → suggest Nuitka (or PyInstaller after
  obfuscation).
- "Encrypt so it can never be recovered" → not achievable for code the
  interpreter must run; explain the realistic protection model (raise cost of
  reverse-engineering, not make it impossible).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.