$npx -y skills add opendatahub-io/ai-helpers --skill python-packaging-security-auditUse this skill to evaluate the security of a Python package repository by orchestrating static analysis, binary scanning, and git history inspection sub-skills in parallel, then combining their results into a unified security report with a risk rating.
| 1 | # Python Packaging Security Audit |
| 2 | |
| 3 | Orchestrates a comprehensive pre-onboarding security evaluation of Python |
| 4 | packages by dispatching three specialized sub-skills as parallel background |
| 5 | agents. Each agent writes its report section to an individual file; the |
| 6 | orchestrator reads all files and assembles the unified report. |
| 7 | |
| 8 | ## Inputs |
| 9 | |
| 10 | - **repo_path** (optional): Local filesystem path to an already-cloned repository |
| 11 | - **package_name** (optional): Python package name — the skill will locate and clone the repository |
| 12 | - **hexora_results** (optional): File path to pre-computed hexora JSON output |
| 13 | (`hexora-results.json`). Forwarded to the `python-packaging-static-audit` |
| 14 | sub-skill. |
| 15 | - **binary_scan** (optional): File path to pre-computed binary scanner JSON output |
| 16 | (`binary-scan.json`). Forwarded to the `python-packaging-binary-audit` sub-skill. |
| 17 | - **malcontent_results** (optional): File path to pre-computed malcontent JSON |
| 18 | output (`malcontent-results.json`). Forwarded to the |
| 19 | `python-packaging-binary-audit` sub-skill. |
| 20 | |
| 21 | At least one of `repo_path` or `package_name` must be provided. If `repo_path` |
| 22 | is given and points to an existing directory, skip straight to Step 2. Otherwise, |
| 23 | use `package_name` to discover and clone the repository. |
| 24 | |
| 25 | When pre-computed scan inputs are provided, `repo_path` is still needed for triage |
| 26 | context (reading source files to understand findings). Always use `--depth 50` |
| 27 | for cloning because the git-audit sub-skill runs its own git history commands |
| 28 | and needs sufficient commit history. |
| 29 | |
| 30 | ## Step 1: Resolve Repository |
| 31 | |
| 32 | If you already have a local repository path, skip to Step 2. |
| 33 | |
| 34 | Otherwise, use the python-packaging-source-finder skill to locate the upstream |
| 35 | repository URL: |
| 36 | |
| 37 | ```text |
| 38 | Skill: python-packaging-source-finder |
| 39 | Args: <package_name> |
| 40 | ``` |
| 41 | |
| 42 | If the skill returns a URL with high or medium confidence, clone it locally with |
| 43 | enough history for the git scan: |
| 44 | |
| 45 | ```bash |
| 46 | CLONE_DIR=$(mktemp -d -t security-audit-XXXXXX) |
| 47 | git clone --depth 50 -- "<repository_url>" "$CLONE_DIR/repo" |
| 48 | ``` |
| 49 | |
| 50 | Use `$CLONE_DIR/repo` as the repo path for Step 2. |
| 51 | |
| 52 | If source-finder returns low confidence or no URL, stop and return a report with |
| 53 | risk rating `needs_review` stating that the source repository could not be |
| 54 | located. |
| 55 | |
| 56 | ## Step 2: Dispatch Parallel Audits |
| 57 | |
| 58 | Create a working directory for the report files: |
| 59 | |
| 60 | ```bash |
| 61 | AUDIT_DIR=$(mktemp -d -t security-audit-results-XXXXXX) |
| 62 | ``` |
| 63 | |
| 64 | Dispatch three background agents **in parallel**. Each agent invokes one sub-skill |
| 65 | and writes its findings to an individual file. The orchestrator does not need the |
| 66 | intermediate reasoning context — only the final report sections matter. |
| 67 | |
| 68 | When pre-computed scan inputs are available, forward them to the corresponding |
| 69 | sub-skill so it skips tool execution and goes straight to triage. |
| 70 | |
| 71 | **Agent 1 — Static Analysis:** |
| 72 | |
| 73 | ```text |
| 74 | Dispatch a background Agent that invokes the python-packaging-static-audit skill |
| 75 | with repo_path=<repo-path> and output_file=$AUDIT_DIR/static-audit.md. |
| 76 | If hexora_results is provided, also pass hexora_results=<path>. |
| 77 | Then exits. |
| 78 | ``` |
| 79 | |
| 80 | **Agent 2 — Binary Scan:** |
| 81 | |
| 82 | ```text |
| 83 | Dispatch a background Agent that invokes the python-packaging-binary-audit skill |
| 84 | with repo_path=<repo-path> and output_file=$AUDIT_DIR/binary-audit.md. |
| 85 | If binary_scan is provided, also pass binary_scan=<path>. |
| 86 | If malcontent_results is provided, also pass malcontent_results=<path>. |
| 87 | Then exits. |
| 88 | ``` |
| 89 | |
| 90 | **Agent 3 — Git History:** |
| 91 | |
| 92 | ```text |
| 93 | Dispatch a background Agent that invokes the python-packaging-git-audit skill |
| 94 | with repo_path=<repo-path> and output_file=$AUDIT_DIR/git-audit.md, then exits. |
| 95 | ``` |
| 96 | |
| 97 | Wait for all three agents to complete before proceeding. |
| 98 | |
| 99 | ## Step 3: Combine Results |
| 100 | |
| 101 | Read each output file. The first line of each file contains `RISK_RATING:<value>`. |
| 102 | Extract the risk rating and the markdown report section from each file. |
| 103 | |
| 104 | If a file is missing or empty, treat that phase as `risk_rating = needs_review` |
| 105 | and state in the report section that the sub-skill did not produce output. |
| 106 | |
| 107 | Assign the **overall risk rating** as the worst (most severe) rating across all |
| 108 | phases: |
| 109 | |
| 110 | - **no_issues** — All sub-skills returned no_issues |
| 111 | - **low_risk** — Worst sub-skill rating is low_risk |
| 112 | - **needs_review** — At least one sub-skill returned needs_review |
| 113 | - **critical** — At least one sub-skill returned critical |
| 114 | |
| 115 | Precedence: **critical > needs_review > low_risk > no_issues** |
| 116 | |
| 117 | ## Step 4: Cleanup |
| 118 | |
| 119 | Clean up temporary directories: |
| 120 | |
| 121 | ```bash |
| 122 | rm -rf -- "${AUDIT_DIR}" |
| 123 | |
| 124 | if [ -n "${CLONE_DIR}" ] && [[ "${CLONE_DIR}" == "${TMPDIR:-/tmp}"/* ]]; then |
| 125 | rm -rf -- "${CLONE_DIR}" |
| 126 | else |
| 127 | echo "ERROR: refusing to delete '${CLONE_DIR}' -- not under temp dir" >&2 |
| 128 | fi |
| 129 | ``` |
| 130 | |
| 131 | ## |