Python secure coding
Skill konstruktoid/agent-instructions-skills/skills/python/python-secure-coding
A library of reusable instructions and Claude Code skills for AI coding agents.
npx -y skills add konstruktoid/agent-instructions-skills --skill python-secure-codingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 19 days oldThe repository was created 19 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Authors and modifies Python source code with security best practices that static analysis alone does not fully cover, including input handling, deserialization, secrets, subprocess/SQL/crypto usage, SSRF, and dependency hygiene, layered on the ruff/ty quality gate. Use when writing or editing Python, and especially for changes touching user input, subprocess/OS calls, SQL or other query construction, templating, cryptography, secrets/credentials, or access control.
SKILL.md
9.2 KB, as published. Nobody here has run it
python-secure-coding
Purpose
Produce Python code that passes the repository's ruff and ty checks cleanly, and that
additionally follows Python security best practices no linter fully verifies on its own. This
skill is a triage layer: it routes the change to the security detail that applies to it, then
holds the change to a bounded verify loop. The per-category detail lives in references/, read on
demand rather than up front.
When to use this
- Authoring or modifying Python source in a repository that adopts these instructions.
- Any change that touches user input, deserialization, subprocess/OS/shell calls, SQL or other query construction, templating, cryptography, passwords, secrets/credentials, server-side HTTP requests to user-influenced destinations, or access control.
When NOT to use this
- Non-Python changes.
Steps
- Read the tooling baseline in
instructions/python_coding_instructions.md(see below) and follow it. It is the single source of truth for theruff/tyworkflow and for the judgment items no tool checks. - Identify which change types in the triage table below the change matches, and read those reference files. Read only what applies; the table is the index, not a reading list.
- Write or modify the code, applying that guidance.
- Run the verify loop below until it is clean or the bound is reached.
- State the security reasoning for any non-obvious call in the commit message or PR description.
Tooling baseline
The ruff/ty baseline is defined in instructions/python_coding_instructions.md. Read that file
rather than relying on a summary. In short:
- Run the tools through the repository's package manager (
uv run ruff check,uv run ty check). - Run
ruff check,ruff format --check, andty checkyourself. Do not merely describe them. - Do not weaken configuration or add a suppression as a first response to a failing check.
- The instructions file also lists the judgment items no tool checks (docstring accuracy, domain naming, security rationale, boundary-only validation, batching, suppression justification). Apply them; they are not repeated here.
Two points matter specifically for security:
- Lint configuration. Leave an existing ruff or lint configuration alone, per the rule in the
instructions file.
select = ["ALL"]is something to propose for a new project, or when the user asks for stricter linting, not something to impose on a repository that has already chosen its rules. A full rule set is what pulls inS(flake8-bandit),BLE,TRY,ASYNC, andPERF, so where it is absent, expect thinner security lint coverage and lean harder on the references below. S-rule suppressions. Never disable anS(bandit) rule repository-wide to silence one instance. Suppress narrowly at the call site, with a one-line justification.
Triage: which reference to read
Ruff's S rules catch many insecure patterns syntactically, but cannot trace data flow, judge
trust boundaries, or check runtime configuration. Treat an S-rule pass as a floor, not proof of
security. Match the change against this table and read the files that apply:
| The change touches | Read |
|---|---|
| User input, request parameters, uploaded or scraped data | references/injection.md |
| SQL or other query construction, ORM raw queries | references/injection.md |
subprocess, os.system, shell strings, eval/exec | references/injection.md |
| HTML templating or any rendered output | references/injection.md |
| Regular expressions applied to untrusted input | references/injection.md |
pickle, marshal, shelve, yaml.load, XML parsing | references/deserialization.md |
Secrets, API keys, tokens, credentials, .env handling | references/secrets.md |
| Password hashing, token generation, randomness, token comparison | references/secrets.md |
| Logging of anything user-controlled or sensitive | references/secrets.md and references/injection.md |
| Encryption, signing, TLS settings, certificate verification | references/crypto-tls.md |
| Authentication, authorization, permissions, file modes, DB grants | references/access-control.md |
| Server-side HTTP requests to user-influenced URLs or hosts (SSRF) | references/access-control.md |
except around an auth or crypto check, assert as a guard, debug config | references/access-control.md |
| Temp files, locking, shared mutable state (TOCTOU) | references/access-control.md |
| Adding, upgrading, or pinning a dependency | references/supply-chain.md |
If the change matches nothing in the table, the tooling baseline and the verification checklist still apply.
Verify
Never declare a change done from the edit alone. Run every check through the repository's package manager rather than as a bare binary, so it uses the pinned versions:
uv run ruff check ., with no new ignores.uv run ruff format --check ..uv run ty check, with no new suppressions.- The repository's dependency vulnerability scanner, if one is configured, when dependencies changed.
The bounded loop
One attempt is one full fix-and-rerun cycle: apply fixes for the findings from the previous run, then rerun every check above to completion. Reading output, or re-reading a file without changing anything, is not an attempt.
- Baseline the loop at 3 attempts.
- Continue past 3 only while making measurable progress, meaning each cycle ends with strictly fewer findings than the one before it.
- Stop early, before 3 attempts, if the loop is oscillating: the same findings recur, the count stops dropping, or a fix for one finding reintroduces another.
- When stopping for either reason, report to the user rather than proceeding or silently giving up. Name the failing check, include its output, and state what was tried.
Verification checklist
- Verify loop run to a clean result, or stopped under the rules above with unresolved issues reported, naming the failing check and its output
-
uv run ruff check .clean -
uv run ruff format --check .clean -
uv run ty checkclean - No new or weakened lint or type-check suppressions without a one-line justification, and no
repository-wide
S-rule disabling - Untrusted input (user input, network/API responses, files) is validated/sanitized at the boundary, not assumed safe downstream, with ReDoS-prone regexes avoided
- No untrusted data reaches
eval/exec,subprocess/os.systemwithshell=True,pickle/yaml.load, or string-built SQL - Server-side requests to user-influenced URLs/hosts are validated against an allowlist (SSRF)
- Secrets/credentials traced end-to-end: not hardcoded, not logged, not in tracebacks or
responses; secret/token comparisons use
secrets.compare_digest/hmac.compare_digest - Passwords hashed with bcrypt/Argon2; security-sensitive randomness uses
secrets, notrandom - Authorization enforced server-side; security checks fail closed; debug mode off in production config
- Dependency changes checked against the repository's existing vulnerability scanner (if any)
- Every reference file matched in the triage table was read and applied
References
Paths starting instructions/ are relative to this library's root. When this skill is installed
as a Claude Code plugin, read them at ${CLAUDE_PLUGIN_ROOT}/instructions/, which resolves to the
installed copy.
Normative
Cite these as standards.
- OWASP, Top 10:2025
- OpenSSF, Secure Coding Guide for Python
Background
Useful orientation, but not authoritative. Do not cite these as standards; where they conflict with a normative source, the normative source wins.
- RealPython, Security Best Practices
- SimeonOnSecurity, Python Security Best Practices: Protecting Your Code and Data
- Snyk, Python Security Best Practices Cheat Sheet
- Astral, Vulnerability and malware checks in uv:
uv auditstatus and usage