# openssf-python-review

Perform adversarial Python security code reviews grounded in the OpenSSF Secure Coding Guide for Python. Use when Codex needs to audit large Python repositories, recovered or decompiled Python source, Python services or scripts with unclear trust boundaries, or code paths involving Python-specific injection, deserialization, archive extraction, import-path, encoding, numeric, concurrency, logging, exception, resource-management, secret-handling, or randomness risks.

- **Kind:** skill
- **Source:** https://github.com/SpecterOps/skills
- **Page:** https://forefy.com/skills/cec0af5e-71e7-4f31-ae43-a67d60e854bb
- **API (JSON + files):** https://forefy.com/api/asr/cec0af5e-71e7-4f31-ae43-a67d60e854bb

---

## SKILL.md

---
name: openssf-python-review
description: Perform adversarial Python security code reviews grounded in the OpenSSF Secure Coding Guide for Python. Use when Codex needs to audit large Python repositories, recovered or decompiled Python source, Python services or scripts with unclear trust boundaries, or code paths involving Python-specific injection, deserialization, archive extraction, import-path, encoding, numeric, concurrency, logging, exception, resource-management, secret-handling, or randomness risks.
---

# OpenSSF Python Review

Use this skill for manual Python review when the result needs OpenSSF Python rule coverage plus the evidence standard of the local OWASP and CWE review skills. Prefer a narrower framework or platform skill when one clearly fits; use this skill to drive Python-specific adversarial review and to make recovered-source uncertainty explicit.

## Review Principles

- Start from architecture, trust boundaries, attacker-controlled inputs, sensitive assets, privilege levels, and Python runtime assumptions.
- Treat OpenSSF rules as coverage prompts and root-cause clues, not as proof. Confirm a reachable path before reporting a finding.
- Prioritize paths that cross trust zones or reach code execution, deserialization, query execution, archive extraction, filesystem, import resolution, secrets, authorization, logs, error output, randomness, and shared state.
- Assume attackers will exploit alternate encodings, malformed archives, crafted object state, client-controlled identity fields, poisoned environment variables, thread timing, exceptional control flow, and recovered-source gaps.
- Distinguish confirmed vulnerabilities from suspicious patterns, hardening opportunities, and unanswered questions.
- For recovered source, separate what is visible in code from what may be missing because of decompilation, packaging, generated wrappers, native extensions, or absent deployment configuration.
- Use the guide's linked CWE as an initial mapping candidate. Validate the primary CWE with the local `cwe-code-review` skill when precise mapping matters or when the guide's CWE is broader than the proven root cause.
- Always create or update one standalone `poc_<finding_slug>.py` artifact per confirmed finding in the review workspace.

## References

- Read [references/openssf-python-rule-index.md](references/openssf-python-rule-index.md) first for source scope, rule coverage, CWE candidates, and the rule-to-review map.
- Read [references/large-python-project-triage.md](references/large-python-project-triage.md) when scoping a repository-scale baseline or diff-based review and maintaining a coverage ledger.
- Read [references/python-trust-boundary-surfaces.md](references/python-trust-boundary-surfaces.md) when tracing untrusted input to authorization, encoding, injection, filesystem, archive, deserialization, import-path, logging, error, secret, or randomness sinks.
- Read [references/python-state-and-availability-surfaces.md](references/python-state-and-availability-surfaces.md) when reviewing numeric correctness, exception behavior, thread pools, races, deadlocks, cleanup, assertions, return values, and other integrity or availability paths.
- Read [references/recovered-python-source-review.md](references/recovered-python-source-review.md) when source was recovered from bytecode, wheels, frozen binaries, containers, partial exports, or decompilers, or when project structure and runtime assumptions are incomplete.

## Review Process

1. Build a Python-aware inventory.
   - Identify packages, entry points, frameworks, CLI commands, workers, schedulers, message consumers, plugins, imports, native bindings, templates, configuration loaders, secrets providers, storage, and deployment/runtime boundaries.
   - Identify Python version assumptions, dependency manifests, generated code, vendored packages, bytecode-only areas, and native or C-extension handoffs.
   - Record which components run under distinct OS identities or trust zones and which share one interpreter, filesystem, environment, cache, or database role.

2. Model attacker positions and trust boundaries.
   - Enumerate HTTP/RPC parameters, headers, cookies, uploaded files, archives, queues, task payloads, database records, environment variables, config files, command-line arguments, import paths, plugin names, serialized blobs, and operator-controlled inputs.
   - Mark security decisions that depend on client-supplied identity, role, tenant, path, locale, encoding, type, numeric value, or exception behavior.
   - For recovered source, note missing call sites, unresolved imports, placeholder names, dead code uncertainty, and configuration that must be verified outside the recovered tree.

3. Triage high-risk Python surfaces first.
   - Trace untrusted data to `subprocess`, `os.system`, SQL execution, `pickle`, `marshal`, YAML/object loaders, archive extractors, path resolution, dynamic import, `eval`/`exec`, logging, error rendering, secret loading, and token generation.
   - Check canonicalization before validation, allowlists over denylists, consistent encodings, server-side access decisions, and import/search-path integrity.
   - Review packaging and deployment artifacts for embedded secrets, debug tools, monkey patches, permissive environment inheritance, and shared-process trust-zone collapse.

4. Review integrity and availability paths.
   - Inspect numeric conversions, `Decimal` construction, float comparisons, special float values, fixed-width or C-backed numbers, bitwise arithmetic, and loop counters when they influence money, quotas, sizes, timeouts, authorization, or resource limits.
   - Inspect exception handling, `finally` blocks, return-value handling, assertions, cleanup, locks, thread pools, shared mutable state, thread-local reuse, and silent worker failures.
   - Treat business-state corruption, fail-open behavior, denial of service, and audit blind spots as security issues when an attacker can influence the path.

5. Validate each candidate end to end.
   - Trace `source -> parsing -> normalization -> validation -> authorization -> transformation -> sink -> impact`.
   - Identify the attacker capability, required state, bypassed or missing control, Python behavior that makes the path exploitable, and concrete impact.
   - Read the relevant reference section and rule entry before naming an OpenSSF rule or CWE.
   - Keep scanner hits, dangerous APIs, and decompiler oddities as leads until the full path is proven.

6. Build PoC artifacts.
   - Create or update one standalone `poc_<finding_slug>.py` file for each confirmed finding.
   - Make each PoC incremental: print or implement numbered steps for prerequisites, material acquisition, trigger, impact verification, and cleanup guidance.
   - State attacker position, required permissions, credentials or certificates, environmental dependencies, Python/runtime assumptions, and any unproven prerequisite before sending requests or touching state.
   - Default to dry-run or harmless markers and require an explicit flag for state-changing validation.
   - If a finding has no safe runnable path, still create its per-finding PoC scaffold and explain the missing prerequisite or unsafe step.
   - Validate each script with syntax checks and dry runs, then record which live steps were and were not executed.

## Finding Standard

Lead with findings ordered by severity. For each finding include `Severity`, `Location`, `Issue`, `OpenSSF Rule`, `CWE`, `Evidence`, `Exploit Path`, `Impact`, `Remediation`, `Test`, and `PoC Requirements`.

For `OpenSSF Rule`, include the `pyscg-XXXX` identifier, rule name, and one sentence explaining why the code path violates that rule. If multiple rules contribute, name one primary rule and mention secondary rules only when they explain a distinct contributing failure.

For `CWE`, include the identifier, name, and one sentence explaining why that entry is the precise root-cause mapping. If the guide's CWE is only a candidate or a broad mapping, say so and validate with the local CWE corpus before presenting it as primary.

For `Evidence`, include line-scoped fenced code blocks with an appropriate language tag such as `python`, `toml`, `yaml`, `json`, `bash`, `sql`, or `dockerfile`. Put the source path and line range immediately above each block. Keep excerpts narrow enough to show the input, missing control, Python behavior, and sink without dumping whole modules.

For each finding, reference the corresponding `poc_<finding_slug>.py` artifact and include the minimum attacker position, required permissions or credentials, environmental conditions, safe default behavior, and example invocation.

After findings, include `Open Questions / Assumptions` and `Coverage`. In `Coverage`, list reviewed Python packages, entry points, trust boundaries, OpenSSF rule groups applied, recovered-source gaps, and tests or live validation not performed. If no confirmed findings exist, say so explicitly and still state unresolved risks, review gaps, and that no per-finding PoC artifacts were created.

## agents

```

```

## agents/openai.yaml

```yaml
interface:
  display_name: "OpenSSF Python Review"
  short_description: "Review Python code with OpenSSF guidance"
  default_prompt: "Use $openssf-python-review to audit this Python codebase with an adversarial OpenSSF-guided review and prioritized findings."
```

## references

```

```

## references/large-python-project-triage.md

# Large Python Project Triage

Use this reference to keep a repository-scale review focused, reproducible, and evidence-driven.

## Contents

- Review modes
- Inventory sequence
- Priority order
- Search anchors
- Coverage ledger
- Escalation rules

## Review Modes

- Use a baseline review for a new repository, a recovered source tree, a major release, a post-incident review, or a codebase with unknown trust boundaries.
- Use a diff-based review for a pull request or narrow change, but expand to baseline review when the change introduces a new parser, integration, trust boundary, secret, worker, archive, plugin, or privileged path.
- Use a recovered-source review whenever the tree lacks original source fidelity, even if the repository is large and otherwise complete.

## Inventory Sequence

1. Identify execution surfaces.
   - Find `pyproject.toml`, `setup.py`, `setup.cfg`, `requirements*.txt`, lockfiles, `Pipfile`, `tox.ini`, `noxfile.py`, Dockerfiles, service definitions, and deployment manifests.
   - Find `__main__.py`, console entry points, ASGI/WSGI apps, Celery/RQ/Dramatiq workers, cron jobs, migrations, CLI modules, plugins, import hooks, and notebooks.
   - Find framework routing, task registration, serializers, command handlers, and event consumers.

2. Identify security assets and trust boundaries.
   - Map user identities, service identities, tenants, admin roles, secrets, key material, databases, object stores, caches, queues, uploaded files, generated reports, and external APIs.
   - Mark which inputs are remote, authenticated, tenant-controlled, operator-controlled, environment-controlled, or only locally writable.
   - Mark which components share OS identity, filesystem, import path, database role, cache, or queue.

3. Identify Python-specific sink clusters.
   - Search for command execution, SQL, deserialization, archive extraction, dynamic import, path handling, encoding conversion, logging, error rendering, randomness, thread pools, temporary files, and assertions.
   - Read the surrounding module and its callers instead of reporting from a search hit alone.
   - Cluster repeated helpers so one root cause is not reported as many duplicate symptoms.

4. Trace the most exposed paths first.
   - Start with unauthenticated routes, file uploads, webhooks, queue consumers, parser entry points, import/plugin loaders, admin APIs, secrets/config loaders, and background jobs that act with more privilege than their callers.
   - Then inspect shared helpers and lower-level wrappers that may widen the same flaw across the repository.

5. Keep a coverage ledger while reviewing.
   - Record reviewed package, entry point, trust boundary, rule groups applied, confirmed findings, open questions, and missing runtime evidence.
   - Record skipped packages and why they were lower priority.
   - Record which test, scanner, or live validation steps were not run.

## Priority Order

Use this order unless the threat model gives a stronger reason to change it:

1. Authentication, authorization, tenant isolation, trust-zone separation, and secret handling.
2. Code execution, deserialization, dynamic import, archive extraction, command execution, and SQL.
3. Canonicalization, encoding, path containment, upload handling, and log/error disclosure.
4. Randomness, signing, token creation, and key use.
5. Concurrency, resource exhaustion, cleanup, and background-task failure handling.
6. Numeric integrity and coding-standard rules where they influence security state.

## Search Anchors

Use these as review leads, then trace the path manually:

```bash
rg -n "FastAPI|Flask|Django|Starlette|APIRouter|Blueprint|urlpatterns|add_url_rule|route\\(|@app\\.|@router\\."
rg -n "celery|shared_task|task\\(|rq|dramatiq|cron|schedule|apscheduler|consumer|handler|webhook|callback"
rg -n "subprocess\\.|os\\.system|pickle\\.|shelve|marshal\\.|yaml\\.|zipfile|tarfile|unpack_archive|importlib|__import__|sys\\.path"
rg -n "execute\\(|executescript\\(|raw\\(|text\\(|format\\(|format_map\\(|eval\\(|exec\\("
rg -n "logging\\.|logger\\.|traceback|debug|DEBUG|secret|token|password|api[_-]?key|private[_-]?key"
rg -n "ThreadPoolExecutor|ProcessPoolExecutor|threading\\.local|Lock\\(|Queue\\(|asyncio|Temporary|mkstemp|NamedTemporaryFile|\\bassert\\b"
```

For large repositories, start with file-level counts before reading deeply:

```bash
rg -l "subprocess\\.|os\\.system|pickle\\.|extractall\\(|executescript\\(|sys\\.path|ThreadPoolExecutor|\\bassert\\b" .
rg --files -g '*.py' -g 'pyproject.toml' -g 'setup.py' -g 'requirements*.txt' -g 'Dockerfile*' -g '*.yaml' -g '*.yml'
```

## Coverage Ledger

Maintain a compact working table:

| Surface | Entry point or package | Attacker input | Sensitive sink or decision | Rules applied | Status |
| --- | --- | --- | --- | --- | --- |
| Auth | `api/users.py` | session cookie, JSON body | role and tenant check | `pyscg-0055`, `pyscg-0040` | reviewed / open / finding |
| Upload | `workers/archive.py` | ZIP upload | extraction path and worker FS | `pyscg-0012`, `pyscg-0044` | reviewed / open / finding |
| Queue | `tasks/import.py` | broker payload | `pickle.loads` | `pyscg-0023` | reviewed / open / finding |

Keep notes on:

- caller and sink locations
- trust assumptions not visible in source
- alternate routes or workers that reuse the same helper
- whether the same root cause affects multiple files
- whether a PoC or regression test exists

## Escalation Rules

- Expand from a module to the whole repository when a shared helper performs auth, validation, serialization, logging, config loading, command execution, or path handling.
- Expand from a diff to baseline review when a new dependency, worker, plugin, parser, archive format, or deployment boundary appears.
- Escalate a suspicious pattern to a finding only when attacker influence, missing control, reachability, and impact are all supported.
- Escalate a recovered-source gap to an open question when the missing artifact could materially change exploitability.

## references/openssf-python-rule-index.md

# OpenSSF Python Rule Index

Use this reference first to scope coverage and choose the rule pages relevant to a suspected Python weakness.

## Contents

- Source scope
- How to use the index
- High-priority rule groups
- Rule map
- Coverage notes

## Source Scope

- Source: OpenSSF Secure Coding One Stop Shop for Python.
- Snapshot basis: upstream `main` tree inspected on 2026-07-23 at Git tree `79c851adf711e4b8878b35b37397f828c25a9c0b`.
- Guide scope: CPython 3.9 and later, with standard-library-focused examples and rule pages named `pyscg-XXXX`.
- Rule count in this snapshot: 48 rules across Introduction, Encoding and Strings, Numbers, Neutralization, Exception Handling, Logging, Concurrency, Coding Standards, and Cryptography.
- The guide maps each rule to one or more CWE entries. Treat those as mapping candidates until the reviewed code path proves the root cause.
- The guide examples are intentionally narrow teaching examples. Do not copy a compliant sample into production or assume it addresses adjacent risks outside the named rule.

## How To Use The Index

- Start with architecture and attacker-controlled inputs, then use the table to widen coverage.
- Prioritize rules that reach a trust boundary, code execution, data disclosure, authorization decision, secret, log, error output, or availability limit.
- Read the topic reference for the relevant rule group before reporting.
- Use the `cwe-code-review` skill when a finding needs a more precise CWE than the guide's candidate.
- Keep rules that are not reachable from attacker influence as hardening notes or coverage items, not confirmed findings.

## High-Priority Rule Groups

| Group | Rules | Why prioritize |
| --- | --- | --- |
| Trust and identity | `pyscg-0040`, `pyscg-0041`, `pyscg-0055` | Shared runtimes, embedded secrets, or client-controlled roles can collapse the security model. |
| Input normalization and neutralization | `pyscg-0043`, `pyscg-0044`, `pyscg-0045`, `pyscg-0047`, `pyscg-0008`, `pyscg-0009`, `pyscg-0010` | Alternate encodings and unsafe sinks commonly turn user input into code, queries, or policy bypasses. |
| Files, imports, and object loading | `pyscg-0012`, `pyscg-0013`, `pyscg-0023`, `pyscg-0011` | Archives, search paths, deserialization, and external binary data can cross into execution or arbitrary file effects. |
| Observability and leakage | `pyscg-0019`, `pyscg-0020`, `pyscg-0021`, `pyscg-0022`, `pyscg-0050` | Logs and debug tooling can leak secrets, hide attacks, or expose new privileged functionality. |
| Integrity and availability | `pyscg-0001` to `pyscg-0007`, `pyscg-0014` to `pyscg-0018`, `pyscg-0024` to `pyscg-0037`, `pyscg-0051`, `pyscg-0052` | Numeric, exception, resource, and concurrency failures become security issues when attackers can drive state or load. |
| Randomness | `pyscg-0038` | Predictable tokens, IDs, or secrets undermine authentication and confidentiality. |

## Rule Map

### 01 Introduction

| Rule | CWE candidate | Review focus | Common leads |
| --- | --- | --- | --- |
| `pyscg-0040` Use Process Isolation for Trust Zones | CWE-501 | Separate less-trusted code or data processing from sensitive runtime privileges. | Shared interpreter/UID for web, worker, parser, admin, or tenant workloads; no OS isolation around risky parsing. |
| `pyscg-0041` Externalize Configuration and Secrets | CWE-798 | Keep credentials, keys, and deployment-specific trust material out of code and replaceable at runtime. | Hardcoded passwords, API keys, certs, tokens, backend IPs, service accounts, `.pyc`-recoverable constants. |
| `pyscg-0042` Ensure Correct Operator Precedence | CWE-783 | Verify expressions that combine assignment, comparison, or mutation do not produce unintended security state. | Dense boolean expressions, chained reads/writes, policy checks mixed with side effects, arithmetic used in bounds checks. |
| `pyscg-0055` Determine Access on Server Side | CWE-472 | Derive identity and permissions from trusted server-side state, not client-supplied fields. | `role`, `user`, `tenant`, `is_admin`, or action scope accepted from form/JSON/query data without verified session binding. |

### 02 Encoding and Strings

| Rule | CWE candidate | Review focus | Common leads |
| --- | --- | --- | --- |
| `pyscg-0043` Specify Locale Explicitly | CWE-175 | Prevent locale-dependent parsing, formatting, or comparisons from changing security behavior. | Locale-sensitive dates, numbers, case handling, implicit process locale, user-controlled locale selection. |
| `pyscg-0044` Canonicalize Input Before Validating | CWE-180 | Normalize equivalent representations before validation or policy checks. | Path validation before `.resolve()`, Unicode confusables, mixed normalization forms, encoded traversal, case-folding mismatch. |
| `pyscg-0045` Enforce Consistent Encoding | CWE-176 | Keep text encoding stable across trust boundaries and sanitization steps. | Implicit `.encode()`/`.decode()`, fallback codecs, lossy ASCII conversion, different producer/consumer encodings, forensic parsers. |

### 03 Numbers

| Rule | CWE candidate | Review focus | Common leads |
| --- | --- | --- | --- |
| `pyscg-0001` Control Numeric Precision | CWE-1339 | Avoid floating-point drift in security-relevant amounts, quotas, or comparisons. | Money, billing, limits, percentages, resource accounting, token expiry math using `float`. |
| `pyscg-0002` Guard Fixed-Width Numbers Against Overflow | CWE-191, CWE-190 | Check C-backed or fixed-width numeric boundaries explicitly. | `numpy`, `ctypes`, `struct`, `datetime.timedelta`, native bindings, size or timestamp conversions. |
| `pyscg-0003` Use Arithmetic Over Bitwise Operations | CWE-1335 | Keep arithmetic semantics clear where bounds or permissions depend on numeric state. | Shifts used as multiply/divide, mixed bitwise and arithmetic operations, signed values, packed flags. |
| `pyscg-0004` Use Integer Loop Counters | CWE-197 | Avoid float counters that skip, repeat, or never terminate. | Float increments in retry, pagination, timeout, rate, or resource loops. |
| `pyscg-0005` Specify Rounding for Numeric Conversions | CWE-197 | Make truncation and rounding decisions explicit. | `int(float_value)`, quota or price conversion, timestamps, percentage thresholds, size calculations. |
| `pyscg-0006` Use an Appropriate Comparator for Numbers | CWE-681 | Compare numeric values as numbers with appropriate tolerance or decimal semantics. | String comparison of amounts or versions, direct float equality, `Decimal` mixed with floats. |
| `pyscg-0007` Use String Literals for Decimal Construction | CWE-681 | Construct decimals from exact text, not binary float approximations. | `Decimal(0.1)`, monetary constants, tax or fee tables, threshold constants. |

### 04 Neutralization

| Rule | CWE candidate | Review focus | Common leads |
| --- | --- | --- | --- |
| `pyscg-0047` Use Allow Lists Over Deny Lists | CWE-184 | Prefer accepted forms over trying to enumerate malicious forms. | Character stripping, regex denylists, extension denylists, filter lists for HTML, paths, commands, or identifiers. |
| `pyscg-0008` Prevent Format String Injection | CWE-134 | Keep the format template static when attacker data is formatted. | User-controlled `.format()` or `format_map()` templates, translation strings, templated errors, access to `__globals__`. |
| `pyscg-0009` Prevent OS Command Injection | CWE-78 | Avoid mixing lesser-trusted data into command lines; prefer Python APIs. | `subprocess`, `os.system`, `shell=True`, string-built argv, `shlex.split`, user-selected executable/flags, hostile filenames. |
| `pyscg-0010` Prevent SQL Injection | CWE-89 | Keep SQL code separate from data and avoid script execution paths. | f-strings, `%`, `.format()`, concatenation, `executescript()`, raw ORM fragments, dynamic identifiers. |
| `pyscg-0011` Prevent Type Confusion | CWE-843 | Preserve signedness, width, and expected type when consuming external binary or native data. | `struct.unpack`, `ctypes`, foreign-function data, protocol fields, signed/unsigned conversions. |
| `pyscg-0012` Extract Archives Safely | CWE-409 | Stop traversal, bombs, hostile links, and unbounded extraction effects. | `extractall()`, `extract()`, `tarfile`, `zipfile`, `shutil.unpack_archive`, member paths, count/size limits, symlinks. |
| `pyscg-0013` Secure Search Paths | CWE-426 | Keep module and executable resolution out of attacker-controlled directories and environment. | `sys.path`, `PYTHONPATH`, cwd imports, `sitecustomize`, plugin loading, environment inheritance, writable import dirs. |
| `pyscg-0023` Secure Deserialization | CWE-502 | Avoid object deserialization across trust boundaries or verify integrity before use. | `pickle.loads`, `pickle.load`, `shelve`, serialized cache/queue data, unsigned blobs, gadget-capable object loaders. |

### 05 Exception Handling

| Rule | CWE candidate | Review focus | Common leads |
| --- | --- | --- | --- |
| `pyscg-0014` Use Specific Exception Types | CWE-397 | Make exceptional security states distinguishable and recover only where intended. | Raising `Exception`/`BaseException`, broad handlers around auth, file, or policy code. |
| `pyscg-0015` Handle Error Conditions | CWE-755 | Fail deliberately and visibly instead of continuing after failed security-relevant operations. | Ignored filesystem or network errors, empty `except`, fallback defaults, partial state changes. |
| `pyscg-0016` Propagate Exceptions and Preserve Context | CWE-396 | Preserve failure cause and let the correct layer decide recovery. | `except: pass`, blanket wrapping, discarded `__cause__`, generic retries, fail-open error translation. |
| `pyscg-0018` Validate Numeric Data Beyond Type Checking | CWE-754 | Reject exceptional numeric values such as NaN and infinities when they break invariants. | `float()` on user input, `nan`, `inf`, direct NaN comparison, limits checked only by type. |
| `pyscg-0028` Preserve Exceptions in Finally Blocks | CWE-584 | Avoid `return`, `break`, or `continue` suppressing pending exceptions. | Control flow inside `finally`, hidden validation failures, transaction cleanup that masks errors. |
| `pyscg-0052` Ensure Cleanup on Exceptions | CWE-460 | Restore locks, state, and resources on all exceptional paths. | Manual acquire/release, partially updated state, cleanup skipped after parser or worker failure. |

### 06 Logging

| Rule | CWE candidate | Review focus | Common leads |
| --- | --- | --- | --- |
| `pyscg-0019` Exclude Sensitive Data From Logs | CWE-532 | Keep secrets and personal data out of logs and debug output. | Passwords, tokens, cookies, keys, full request bodies, PII, `print()` debugging, verbose exception data. |
| `pyscg-0020` Implement Informative Event Logging | CWE-778 | Record security-relevant events with enough context for detection and response. | Missing auth failure, authorization denial, admin action, data access, parser rejection, or secret-use audit events. |
| `pyscg-0021` Exclude Developer Tools From the Final Product | CWE-489 | Keep test, debug, monkey-patch, and troubleshooting surfaces out of production packages. | Debug routes, admin helpers, monkey patches, test credentials, profiling hooks, development-only flags. |
| `pyscg-0022` Neutralize Untrusted Data in Logs | CWE-117 | Prevent CRLF and structured-log manipulation. | Raw request values in logs, newline injection, unescaped JSON/log fields, log viewer XSS. |
| `pyscg-0050` Sanitize Error Output to Prevent Information Disclosure | CWE-209 | Separate operator diagnostics from user-visible error output. | Stack traces, paths, SQL errors, secrets in exception text, raw downstream errors, verbose debug responses. |

### 07 Concurrency

| Rule | CWE candidate | Review focus | Common leads |
| --- | --- | --- | --- |
| `pyscg-0024` Ensure Thread Pool Tasks Can Be Interrupted | CWE-400 | Ensure long-running tasks can stop during shutdown or overload. | Blocking tasks, no cancellation signal, stuck worker shutdown, unbounded external calls. |
| `pyscg-0025` Configure Adequate Resource Pools | CWE-410 | Bound worker count and queue growth under attacker-driven load. | Thread-per-request/message, oversized pools, no queue limit, no timeout or grace period. |
| `pyscg-0026` Prevent Deadlocks | CWE-833 | Avoid worker tasks waiting on work scheduled into the same exhausted pool. | Nested `future.result()`, lock ordering, thread-starvation patterns, interdependent subtasks. |
| `pyscg-0027` Prevent Race Conditions | CWE-362 | Synchronize shared state and security decisions. | Shared dict/list/set mutation, check-then-act, chained operations, TOCTOU, missing locks. |
| `pyscg-0029` Reinitialize Reused Thread Objects | CWE-665 | Clear thread-local or reusable worker state between tasks. | `threading.local()`, per-request auth context, tenant data, pooled workers, stale principal leakage. |
| `pyscg-0030` Ensure Thread Pool Tasks Do Not Fail Silently | CWE-392 | Observe worker failures instead of losing security-relevant processing errors. | Ignored `Future`, no `result()`/`exception()`, `map()` exceptions never consumed, silent audit job failure. |

### 08 Coding Standards

| Rule | CWE candidate | Review focus | Common leads |
| --- | --- | --- | --- |
| `pyscg-0031` Use Copies When Modifying Iterables | CWE-1095 | Avoid skipped or inconsistent processing when collections mutate during iteration. | Removing ACLs, sessions, jobs, or filters while iterating the same collection. |
| `pyscg-0032` Avoid Redefining Built-in Functions or Standard Library Identifiers | CWE-1109 | Prevent shadowing that changes security behavior or misleads reviewers. | Variables or modules named `str`, `list`, `id`, `open`, `json`, `os`, `secrets`, `logging`. |
| `pyscg-0033` Implement Comparisons by Value Rather Than Reference | CWE-595 | Use value equality for security state and custom objects. | `is` used for strings/ints/roles, missing `__eq__`, identity-based membership assumptions. |
| `pyscg-0034` Check for None Values | CWE-476 | Handle absent objects and optional returns before dereference or policy use. | `None` from lookup/auth/cache, `len(None)`, attribute access after failed fetch, raising `None`. |
| `pyscg-0035` Complete Resource Cleanup | CWE-459 | Remove temporary artifacts and limit access to them. | Manual temp paths, leaked files, permissive temporary permissions, abnormal termination cleanup gaps. |
| `pyscg-0036` Check Return Values | CWE-252 | Use returned values and sentinel states correctly. | Ignored immutable transforms, unchecked `None`/false returns, failed validation or write results. |
| `pyscg-0037` Presume Assertions May Be Disabled In Production | CWE-617 | Never rely on `assert` for security checks or required validation. | `assert user.is_admin`, `assert token`, `assert path.is_relative_to`, `python -O` exposure. |
| `pyscg-0051` Release Unused Resources | CWE-404 | Close files, sockets, DB handles, and other OS resources deterministically. | Missing `with`, leaked clients, long-lived handles, worker/process resource accumulation. |

### 09 Cryptography

| Rule | CWE candidate | Review focus | Common leads |
| --- | --- | --- | --- |
| `pyscg-0038` Use Sufficiently Random Values | CWE-330 | Use cryptographically strong randomness for security-sensitive values. | `random`, seeded PRNGs, predictable tokens, reset links, session IDs, salts, nonces, generated passwords. |

## Coverage Notes

- Apply every high-priority group that matches an exposed trust boundary, then record which lower-priority groups were sampled or excluded.
- Treat numeric, concurrency, and coding-standard rules as security findings only when the code path can affect confidentiality, integrity, availability, authorization, auditability, or resource isolation.
- The guide is standard-library focused. If the repository uses framework, third-party, native, or cloud-specific APIs, extend the review beyond this index while keeping the same evidence standard.
- For recovered source, record whether a rule could not be evaluated because configuration, native code, generated code, or original symbol information is missing.

## references/python-state-and-availability-surfaces.md

# Python State And Availability Surfaces

Use this reference when attacker-influenced inputs can corrupt security-relevant state, bypass limits, hide failures, or exhaust resources.

## Contents

- Reporting threshold
- Numeric integrity
- Exception and control-flow integrity
- Concurrency and resource exhaustion
- Coding-standard failures with security impact
- Review prompts

## Reporting Threshold

OpenSSF includes rules that look like correctness guidance until an attacker can steer them into a security effect. Report them as findings only when the path can affect:

- authorization, authentication, tenant isolation, or business-state transitions
- money, billing, quotas, rate limits, timeouts, or expiry
- file, socket, database, process, or thread availability
- audit completeness or incident-response evidence
- confidentiality or integrity of data derived from numeric or concurrent state

Otherwise, keep the issue as hardening guidance or a coverage note.

## Numeric Integrity

Apply `pyscg-0001` through `pyscg-0007` and `pyscg-0018` when numeric values influence security decisions.

| Rule | Security-relevant failure mode | Review leads |
| --- | --- | --- |
| `pyscg-0001` Control Numeric Precision | Floating-point drift changes balances, quotas, thresholds, or expiry calculations. | `float` in money, resource accounting, percentage, time, or authorization thresholds. |
| `pyscg-0002` Guard Fixed-Width Numbers Against Overflow | C-backed or fixed-width values wrap, truncate, or raise unexpectedly. | `numpy`, `ctypes`, `struct`, `datetime.timedelta`, FFI, binary protocol lengths, time conversions. |
| `pyscg-0003` Use Arithmetic Over Bitwise Operations | Shifts or bitwise math produce unexpected signed, size, or permission values. | Bit shifts in size, flags, permission masks, rate math, or bounds checks. |
| `pyscg-0004` Use Integer Loop Counters | Float counters skip termination or create unexpected iteration counts. | Retry loops, pagination, polling, throttling, and parser loops using float increments. |
| `pyscg-0005` Specify Rounding for Numeric Conversions | Truncation or implicit rounding changes entitlements, charges, or limits. | `int()` on user-derived floats, timestamp conversion, quota math, percentage conversion. |
| `pyscg-0006` Use an Appropriate Comparator for Numbers | String or exact-float comparisons misorder or misclassify values. | Version, amount, threshold, or rate comparison using strings or `==` on floats. |
| `pyscg-0007` Use String Literals for Decimal Construction | Binary float approximation contaminates exact decimal logic. | `Decimal(<float literal>)` in fees, balances, exchange rates, or fixed policy values. |
| `pyscg-0018` Validate Numeric Data Beyond Type Checking | NaN or infinity bypasses range checks and invariants. | `float()` on request data, direct NaN comparisons, min/max checks without `isfinite()`. |

Check for:

- numeric parsing before range validation
- exceptional float values (`nan`, `inf`, `-inf`) that compare unexpectedly
- fixed-width values crossing Python/native boundaries without explicit range checks
- conversions that silently truncate or round values used in authorization, billing, or resource allocation
- equality or ordering assumptions that differ between string, float, decimal, fraction, and integer representations

Expect:

- integers or exact decimal representations where exactness matters
- explicit rounding decisions
- finite/range validation after parsing and before security decisions
- clear separation between bit flags and arithmetic values
- tests at boundary, overflow, underflow, NaN, infinity, rounding, and precision-loss cases

Useful leads:

```bash
rg -n "Decimal\\(|float\\(|int\\(|round\\(|math\\.isclose|math\\.isnan|math\\.isfinite|numpy|ctypes|struct\\.|timedelta|<<|>>"
rg -n "quota|limit|balance|amount|price|rate|timeout|expires|expiry|ttl|offset|size|length|count|retry"
```

## Exception And Control-Flow Integrity

Apply `pyscg-0014`, `pyscg-0015`, `pyscg-0016`, `pyscg-0028`, and `pyscg-0052` when failures can alter security behavior.

| Rule | Security-relevant failure mode | Review leads |
| --- | --- | --- |
| `pyscg-0014` Use Specific Exception Types | Broad exceptions hide the reason a security control failed. | `raise Exception`, `raise BaseException`, broad handlers in auth, validation, file, or policy code. |
| `pyscg-0015` Handle Error Conditions | Ignored failures leave state partially applied or cause fail-open behavior. | Empty handlers, ignored return codes, fallback values, missing rollback or alerting. |
| `pyscg-0016` Propagate Exceptions and Preserve Context | Wrapped or swallowed failures hide the true control failure. | `except: pass`, blanket rethrow, no `raise ... from`, generic retry loops. |
| `pyscg-0028` Preserve Exceptions in Finally Blocks | `return`, `break`, or `continue` in `finally` discards a pending security exception. | `finally` blocks around transactions, auth, validation, cleanup, or policy checks. |
| `pyscg-0052` Ensure Cleanup on Exceptions | Locks, state, files, or transactions stay inconsistent after failure. | Manual lock release, partial mutation, missing rollback, state restored only on success. |

Check for:

- `except Exception` or bare `except` around authentication, authorization, parsing, validation, signature verification, database writes, file operations, or worker execution
- default values or cached state used after a security-relevant exception
- handlers that log and continue without restoring invariants
- `finally` blocks that mask failures or skip cleanup
- exceptions converted to success responses, empty results, or permissive authorization decisions
- retry logic that repeats state-changing work without idempotency or rollback

Expect:

- specific exceptions and explicit recovery rules
- fail-closed behavior for auth, policy, validation, and integrity checks
- preserved exception cause and enough observability for operators
- `with` statements or equivalent structured cleanup
- tests for the failure path, not only the happy path

Useful leads:

```bash
rg -n "except\\s*:|except Exception|except BaseException|raise Exception|raise BaseException|finally:|return .*finally|break|continue"
rg -n "rollback|commit|lock|acquire\\(|release\\(|transaction|retry|fallback|default|pass$"
```

## Concurrency And Resource Exhaustion

Apply `pyscg-0024` through `pyscg-0030`, plus `pyscg-0051` and `pyscg-0052`, to attacker-driven load and shared state.

| Rule | Security-relevant failure mode | Review leads |
| --- | --- | --- |
| `pyscg-0024` Ensure Thread Pool Tasks Can Be Interrupted | Long-running work cannot stop and drains capacity. | Blocking calls, no cancellation flag, stuck shutdown, unbounded external operations. |
| `pyscg-0025` Configure Adequate Resource Pools | Thread-per-input or unbounded queues enable denial of service. | `ThreadPoolExecutor`, manual threads, no queue bounds, no timeout, no backpressure. |
| `pyscg-0026` Prevent Deadlocks | Workers wait on work that cannot run, freezing service capacity. | Nested `future.result()`, lock ordering, tasks submitted from tasks in the same pool. |
| `pyscg-0027` Prevent Race Conditions | Check-then-act or unsynchronized shared state breaks security invariants. | Shared dict/list/set, token reuse, quota decrement, file TOCTOU, state transitions. |
| `pyscg-0029` Reinitialize Reused Thread Objects | Pooled workers leak prior request or tenant state. | `threading.local()`, auth context, tenant context, reused parser or client objects. |
| `pyscg-0030` Ensure Thread Pool Tasks Do Not Fail Silently | Failed security jobs disappear without alerting or retry. | Ignored `Future`, no `result()`/`exception()`, unconsumed `map()`, silent background failures. |
| `pyscg-0051` Release Unused Resources | Open handles accumulate until the service degrades or fails. | Files, sockets, DB cursors, HTTP clients, subprocess handles, temporary resources. |
| `pyscg-0052` Ensure Cleanup on Exceptions | Exceptional paths leak locks or state and amplify denial of service. | Manual acquire/release, partial worker state, cleanup only on success. |

Check for:

- queue, pool, worker, file, socket, DB connection, parser, or archive limits missing or attacker-controlled
- timeouts absent on external calls or task execution
- cancellation requests that do not reach active work
- locks held while waiting on untrusted I/O or other futures
- shared mutable state updated without atomicity or synchronization
- reused thread-local identity, tenant, request, or authorization context
- task exceptions dropped because futures are never observed
- cleanup paths that depend on normal process termination

Expect:

- bounded pools, queues, timeouts, and backpressure
- cancellation or graceful shutdown paths for long-running work
- minimal lock scope and deterministic lock ordering
- synchronization around security-relevant shared state
- explicit reinitialization of reusable worker context
- observed task failures and security-relevant alerting
- deterministic resource release with `with`, `try/finally`, or close hooks

Useful leads:

```bash
rg -n "ThreadPoolExecutor|ProcessPoolExecutor|Future|submit\\(|map\\(|result\\(|exception\\(|threading\\.local|Lock\\(|RLock\\(|Semaphore|Queue\\("
rg -n "open\\(|socket|requests\\.|httpx\\.|aiohttp|cursor\\(|connect\\(|Temporary|mkstemp|NamedTemporaryFile|close\\("
```

## Coding-Standard Failures With Security Impact

Apply `pyscg-0031` through `pyscg-0037` when language behavior changes a security decision.

| Rule | Security-relevant failure mode | Review leads |
| --- | --- | --- |
| `pyscg-0031` Use Copies When Modifying Iterables | In-place mutation skips revocation, filtering, or cleanup entries. | Removing sessions, ACLs, tokens, jobs, or files while iterating. |
| `pyscg-0032` Avoid Redefining Built-ins Or Standard Library Identifiers | Shadowing changes what a security-sensitive call means. | Variables/modules named `open`, `id`, `str`, `list`, `os`, `json`, `secrets`, `logging`. |
| `pyscg-0033` Implement Comparisons By Value Rather Than Reference | Identity checks misclassify roles, tokens, states, or custom objects. | `is` with strings/ints/enums, missing `__eq__`, custom domain objects in membership checks. |
| `pyscg-0034` Check For None Values | Missing lookup results cause crashes or unsafe fallback behavior. | Optional auth/tenant/user returns, cache misses, dereference before validation. |
| `pyscg-0035` Complete Resource Cleanup | Temporary artifacts remain accessible or exhaust storage. | Manual temp files, permissive temp dirs, cleanup only on success, crash leftovers. |
| `pyscg-0036` Check Return Values | Ignored results leave validation, mutation, or cleanup unapplied. | Immutable transforms not assigned, sentinel returns ignored, failed write/delete/auth checks. |
| `pyscg-0037` Presume Assertions May Be Disabled In Production | `python -O` removes security checks entirely. | `assert` used for role, path, token, signature, amount, or invariant validation. |

Check for:

- assertions in any path that guards security behavior
- `is` used where value equality is intended
- custom objects without equality semantics used in policy or membership decisions
- built-in or standard-library shadowing that makes code review or static analysis misleading
- methods on immutable values whose return is ignored
- iterables changed while processing revocations, allowlists, denylists, or resource cleanup
- temporary files or directories with weak permissions or incomplete cleanup

Expect:

- explicit runtime checks for all required security invariants
- value-based comparisons with clear domain semantics
- unambiguous names for security-sensitive modules and helpers
- return values checked and stored when behavior depends on them
- safe temporary file APIs and deterministic cleanup

Useful leads:

```bash
rg -n "\\bassert\\b|\\bis\\b|__eq__|dataclass|for .* in .*:|\\.remove\\(|\\.pop\\(|\\.discard\\(|tempfile|mkstemp|NamedTemporaryFile"
rg -n "^(open|id|str|list|dict|set|json|os|secrets|logging)\\s*=|def (open|id|str|list|dict|set)\\("
```

## Review Prompts

- Can an attacker choose the value, timing, order, or volume that reaches this path?
- Which invariant is supposed to hold before and after the operation?
- Does an exception, timeout, cancellation, or worker reuse break that invariant?
- Does a numeric edge case bypass a limit or create a different state than the reviewer expects?
- Does the code remain secure under `python -O`, process restart, worker reuse, partial failure, and concurrent requests?
- Which regression test proves the failure before the fix and the invariant after it?

## references/python-trust-boundary-surfaces.md

# Python Trust-Boundary Surfaces

Use this reference when an attacker-controlled value crosses into a Python security decision or high-impact sink.

## Contents

- Review method
- Trust zones and server-side access
- Secrets and configuration
- Locale, encoding, canonicalization, and allowlists
- Format strings, commands, and SQL
- Binary data, archives, search paths, and deserialization
- Logging, errors, and developer tooling
- Randomness

## Review Method

Trace each candidate as:

```text
attacker input -> parser/decoder -> canonicalization -> validation -> authorization -> transformation -> sink -> impact
```

Record:

- attacker position and required state
- exact input carrier and parser
- Python-specific behavior that matters
- existing control and bypass condition
- target asset or invariant
- test or PoC step that proves the path

Do not stop at a dangerous API or scanner hit. Confirm whether the value is attacker-controlled, whether the control is appropriate for the sink, and whether the sink is reachable in the deployed path.

## Trust Zones And Server-Side Access

Apply `pyscg-0040` and `pyscg-0055` when code trusts a process boundary, client field, or shared runtime too much.

Check for:

- less-trusted parsing, plugin, upload, report-generation, or tenant code running under the same OS user and Python runtime as secrets or privileged operations
- workers, web processes, schedulers, and admin jobs sharing one writable filesystem, environment, cache, database role, or import path
- client-provided `user`, `role`, `tenant`, `org`, `scope`, `is_admin`, `permission`, or `action` fields used as authority
- authorization performed only in templates, frontend code, serialized client state, hidden form values, or unsigned JWT claims
- background tasks that accept an object ID or principal from a queue payload without re-authorizing server-side
- policy failures that default to a broad role, anonymous access, or prior cached state

Expect:

- distinct OS identities or equivalent isolation for materially different trust zones
- server-side identity derivation from validated session, token, service identity, or mTLS context
- object, tenant, and action authorization at every read, write, export, and asynchronous transition
- deny-by-default behavior when identity or policy state is absent, malformed, or stale

Useful leads:

```bash
rg -n "is_admin|role|roles|tenant|org_id|session_user|permission|scope|authorize|authz|current_user|request\\.json|form_data"
rg -n "os\\.setuid|os\\.setgid|subprocess|multiprocessing|celery|rq|dramatiq|ThreadPoolExecutor|ProcessPoolExecutor"
```

## Secrets And Configuration

Apply `pyscg-0041` when source, package artifacts, or runtime defaults contain secret or deployment-specific trust material.

Check for:

- passwords, tokens, API keys, private keys, certificate material, connection strings, backend addresses, or default admin credentials in Python constants, test fixtures, package data, notebooks, `.env` files, or recovered `.pyc` constants
- secret values logged, printed, embedded in exception messages, copied into URLs, or passed on process command lines
- code that cannot rotate or reject secrets without a source change or rebuild
- config readers that accept attacker-writable paths, overly broad permissions, or untrusted environment variables
- shared machine identities where per-deployment or per-service identities are expected

Expect:

- runtime secret injection from a protected mechanism with least-privilege access
- replaceable credentials and explicit failure when required secret material is missing
- no secret-bearing debug output or package artifacts
- deployment-specific trust material separated from code and protected by filesystem or platform controls

Useful leads:

```bash
rg -n "(password|passwd|secret|token|api[_-]?key|private[_-]?key|BEGIN [A-Z ]+ PRIVATE KEY|connection[_-]?string|client[_-]?secret)"
rg -n "os\\.environ|getenv|configparser|dotenv|yaml\\.safe_load|tomllib|Path\\(.+config|open\\(.+config"
```

## Locale, Encoding, Canonicalization, And Allowlists

Apply `pyscg-0043`, `pyscg-0044`, `pyscg-0045`, and `pyscg-0047` together when text crosses a trust boundary.

Check for:

- validation before Unicode normalization, path resolution, case folding, percent decoding, or other canonicalization
- producer and consumer components using different encodings or implicit codec defaults
- lossy transformations that can turn rejected text into executable, queryable, or renderable text later
- locale-dependent dates, numbers, sorting, or comparisons in authentication, policy, signature, or accounting flows
- denylists for characters, extensions, commands, HTML, SQL, paths, or identifiers where an allowlist is feasible
- path checks that compare raw strings instead of resolved paths within a trusted base directory
- multiple validation layers that normalize differently, especially across services or queues

Expect:

- one explicit encoding contract per boundary
- canonicalization before validation and before security comparisons
- allowlists for structured identifiers, actions, extensions, encodings, and protocol values
- sink-specific defense after validation, such as parameterization or path containment
- explicit locale handling where locale can affect behavior

Useful leads:

```bash
rg -n "encode\\(|decode\\(|unicodedata|normalize\\(|casefold\\(|lower\\(|upper\\(|locale\\.|setlocale|resolve\\(|relative_to\\(|urlparse|unquote"
rg -n "deny|blacklist|blocklist|replace\\(|re\\.sub|startswith\\(|endswith\\(|allowed|allowlist|whitelist"
```

Questions to answer:

- Which representation is validated?
- Which representation reaches the sink?
- Can an attacker choose the locale, encoding, normalization form, or path separator?
- Does a later decode, render, filesystem, or database layer reinterpret the value?

## Format Strings, Commands, And SQL

Apply `pyscg-0008`, `pyscg-0009`, and `pyscg-0010` to every path where untrusted text becomes instructions for another interpreter.

### Format Strings

Check for:

- attacker-controlled format templates passed to `.format()`, `.format_map()`, `%`, logging templates, translated strings, or custom formatter logic
- format strings that can traverse attributes or globals from exposed objects
- user-controlled templates used in errors, notifications, exports, or localization workflows

Expect:

- static format templates with attacker data passed only as values
- explicit template allowlists or a constrained rendering engine when users may customize output

Useful leads:

```bash
rg -n "\\.format\\(|format_map\\(|%\\s|%\\(|logging\\.(debug|info|warning|error|exception|critical)\\("
```

### Commands

Check for:

- `subprocess`, `os.system`, `os.popen`, shell wrappers, or platform commands receiving untrusted text
- `shell=True`, string-built commands, `shlex.split()` applied to attacker-influenced strings, user-selected executables or flags, and hostile filenames fed into utilities
- `shell=False` calls where arguments still trigger secondary execution, option injection, path lookup, or dangerous tool behavior
- commands used where `pathlib`, `shutil`, `os`, `stat`, archive, or other library APIs would suffice
- inherited `PATH`, working directory, environment, or import/search paths that change executable resolution

Expect:

- Python library APIs over process execution
- fixed executable paths and structured argv when commands are unavoidable
- allowlisted options and end-of-options handling where supported
- least-privilege execution in a dedicated trust zone

Useful leads:

```bash
rg -n "subprocess\\.|Popen\\(|run\\(|call\\(|check_output\\(|os\\.system\\(|os\\.popen\\(|shell\\s*=\\s*True|shlex\\.split"
```

### SQL

Check for:

- f-strings, `%`, `.format()`, concatenation, or `executescript()` around SQL
- raw ORM fragments, dynamic identifiers, order clauses, table names, or filter operators derived from user input
- database APIs that expose shell or scripting extensions
- sanitization presented as the primary SQL defense instead of parameterization

Expect:

- parameterized values
- strict allowlists for identifiers or sort directions that cannot be bound
- no multi-statement script execution with attacker-influenced text

Useful leads:

```bash
rg -n "execute\\(|executemany\\(|executescript\\(|raw\\(|text\\(|SELECT |INSERT |UPDATE |DELETE |ORDER BY|WHERE "
```

## Binary Data, Archives, Search Paths, And Deserialization

### External Binary And Native Data

Apply `pyscg-0011` when Python consumes data from native code, binary protocols, files, or FFI boundaries.

Check for:

- signed/unsigned mismatch in `struct`, `ctypes`, NumPy, or native-extension values
- width truncation before bounds, allocation, length, or authorization decisions
- attacker-controlled size, offset, index, timestamp, or flag values crossing from C-backed representations

Expect:

- exact format declarations
- range validation before use
- conversions that preserve the full valid range and reject impossible values

### Archives

Apply `pyscg-0012` and `pyscg-0044` together to every archive or package extraction path.

Check for:

- `extractall()` or `extract()` without resolved-path containment under a server-selected base directory
- absolute paths, `..`, mixed separators, drive letters, symlinks, hard links, nested archives, deep trees, huge entry counts, and untrusted metadata sizes
- extraction into executable, importable, served, or shared directories
- use of archive metadata alone to enforce decompressed size limits

Expect:

- server-selected extraction root outside sensitive or executable locations
- resolved member path checks before extraction
- file count, actual-read size, nesting, type, and link controls
- resource isolation for untrusted extraction

Useful leads:

```bash
rg -n "zipfile|tarfile|shutil\\.unpack_archive|extractall\\(|extract\\(|ZipFile|TarFile|infolist\\(|getmembers\\("
```

### Search Paths And Imports

Apply `pyscg-0013` when import or executable resolution can be influenced by less-trusted state.

Check for:

- attacker-writable cwd or directories appearing before trusted package paths
- `sys.path.insert`, `PYTHONPATH`, `PATH`, plugin paths, `sitecustomize`, `usercustomize`, or dynamic import names
- execution from writable temp, upload, or extracted directories
- bytecode or package artifacts loaded without integrity expectations
- process launch that inherits an attacker-controlled environment

Expect:

- trusted, immutable import and executable paths
- explicit environment construction for privileged subprocesses
- plugin/package integrity verification where code is loaded dynamically

Useful leads:

```bash
rg -n "sys\\.path|PYTHONPATH|PATH|importlib|__import__|pkgutil|sitecustomize|usercustomize|zipimport|exec_module|entry_points"
```

### Deserialization

Apply `pyscg-0023` to serialized data from requests, queues, caches, files, databases, or IPC.

Check for:

- `pickle.load(s)`, `shelve`, or equivalent object reconstruction on data that can be tampered with
- integrity checks performed after deserialization
- signed payloads with weak key handling or no replay/context binding
- deserialized objects that choose classes, methods, or dynamic behavior
- JSON/YAML or other text formats accepted without schema, type, range, and authorization validation

Expect:

- text-based data formats with explicit schemas where possible
- integrity verification before any unavoidable object deserialization
- strict type, field, and range validation after parsing
- no assumption that data is safe merely because it originated from a once-trusted source

Useful leads:

```bash
rg -n "pickle\\.|shelve|marshal\\.|yaml\\.|loads\\(|load\\(|dill|cloudpickle|joblib"
```

## Logging, Errors, And Developer Tooling

Apply `pyscg-0019`, `pyscg-0020`, `pyscg-0021`, `pyscg-0022`, and `pyscg-0050` together.

Check for:

- secrets, tokens, cookies, authorization headers, PII, or full request/response bodies in logs
- raw attacker text in line-oriented or HTML-viewed logs without CRLF or context-safe handling
- missing audit events for login failures, authorization denials, privilege changes, sensitive reads, parser rejections, secret use, or admin actions
- stack traces, SQL errors, file paths, internal hosts, secrets, or dependency details returned to users
- debug routes, test helpers, monkey patches, profiler hooks, verbose trace flags, or troubleshooting code shipped in production
- `print()` used for security-relevant operational output

Expect:

- structured, sink-safe logs with secret redaction and security event coverage
- operator-only diagnostics separated from user-visible errors
- production packaging that excludes developer tooling and debug-only behavior

Useful leads:

```bash
rg -n "logging\\.|logger\\.|print\\(|traceback|exc_info|debug|DEBUG|monkey|patch|profiler|werkzeug|pdb|breakpoint\\("
rg -n "Authorization|cookie|session|token|password|secret|api[_-]?key|request\\.body|request\\.json"
```

## Randomness

Apply `pyscg-0038` when random values affect authentication, authorization, secrecy, uniqueness, or anti-replay behavior.

Check for:

- `random`, `randint`, `choice`, `shuffle`, seeded PRNGs, timestamps, UUID variants, or process IDs used for tokens, reset links, session IDs, salts, nonces, API keys, generated passwords, invite codes, or CSRF state
- deterministic seeds or test-mode randomness reachable in production
- custom token generation with too little entropy or predictable formatting

Expect:

- `secrets` or OS-backed cryptographic randomness for security-sensitive values
- enough entropy for the attack model
- no reuse of security-sensitive random values across contexts

Useful leads:

```bash
rg -n "import random|random\\.|seed\\(|uuid|token_|nonce|salt|reset|invite|csrf|session_id|api_key"
```

## references/recovered-python-source-review.md

# Recovered Python Source Review

Use this reference when source came from bytecode, wheels, frozen applications, containers, partial exports, code-generation output, or decompilers.

## Contents

- Goal
- Provenance and fidelity
- Reconstruct the execution model
- Handle decompiler and packaging artifacts
- Review workflow
- Evidence and reporting

## Goal

Treat recovered source as an evidence set, not as a perfect source tree. The review still needs a concrete attacker-controlled path and reachable impact, but the report must show which parts are proven from recovered code and which depend on missing runtime or packaging context.

## Provenance And Fidelity

Record before reviewing:

- original artifact type: `.pyc`, wheel, zipapp, PyInstaller bundle, container layer, vendored package, decompiled binary, or partial source export
- Python version and implementation if known
- recovery tool and version if known
- whether line numbers, symbol names, docstrings, annotations, decorators, exception tables, package metadata, and resources were preserved
- whether native extensions, compiled templates, static assets, config files, environment files, migrations, and deployment manifests are present
- whether the tree contains original source mixed with recovered output

Use confidence labels in working notes:

- `confirmed`: visible control flow and data path are sufficient to prove the issue
- `probable`: evidence strongly suggests the path, but a missing artifact or runtime fact still matters
- `open`: a suspicious construct exists, but exploitability cannot be decided from recovered material

Do not report `probable` or `open` items as confirmed vulnerabilities.

## Reconstruct The Execution Model

1. Recover package layout.
   - Find `__main__.py`, `__init__.py`, package metadata, entry points, console scripts, service wrappers, task modules, framework apps, and plugin registration.
   - Map import roots and package names before assuming a module is reachable.

2. Recover runtime boundaries.
   - Identify web, worker, scheduler, CLI, parser, migration, and admin components.
   - Identify where code likely runs under separate processes, OS identities, containers, or serverless handlers.
   - Note when the recovered tree cannot prove whether `pyscg-0040` process isolation exists.

3. Recover trust inputs.
   - Find request, CLI, file, archive, queue, database, environment, config, plugin, and IPC parsing code.
   - Track serialized data, dynamic imports, generated paths, and values copied into logs or errors.
   - When a caller is missing, state what input source would need to be confirmed.

4. Recover sensitive sinks.
   - Find subprocess, SQL, deserialization, archive extraction, path, import, secret, random, thread-pool, temp-file, and error/logging surfaces.
   - Trace back from sinks when entry points are missing or names are poor.

Useful leads:

```bash
rg -n "__main__|entry_points|console_scripts|FastAPI|Flask|Django|ASGI|WSGI|celery|shared_task|ThreadPoolExecutor|ProcessPoolExecutor"
rg -n "subprocess\\.|os\\.system|pickle\\.|marshal\\.|shelve|zipfile|tarfile|extractall\\(|importlib|__import__|sys\\.path|execute\\(|executescript\\("
rg -n "co_filename|<lambda>|<listcomp>|<dictcomp>|<module>|LOAD_GLOBAL|site-packages|dist-info|egg-info"
```

## Handle Decompiler And Packaging Artifacts

Expect ambiguity around:

- lost or shifted line numbers
- synthetic variable names and flattened comprehensions
- reconstructed `try`/`except`/`finally` blocks that obscure exception behavior
- lost decorators or descriptors that change authorization, routing, serialization, or validation
- constant folding that hides the original secret or comparison expression
- optimized bytecode that removed `assert` statements
- generated wrappers that hide framework checks or middleware
- missing package resources, templates, migrations, or configuration defaults
- missing native extensions or CFFI/ctypes targets
- duplicated vendored code that is not actually reachable

Verify before concluding:

- whether an odd expression is a decompiler artifact or real logic
- whether a missing validation step might exist in middleware, a decorator, a native extension, or generated code
- whether a dangerous helper is imported and reachable from an entry point
- whether an apparent secret is a real credential, a fixture, or a dead constant
- whether `assert`-based checks disappeared because the artifact was optimized

## Review Workflow

1. Start with sinks, not style.
   - Search for high-impact OpenSSF surfaces first: `pyscg-0055`, `pyscg-0041`, `pyscg-0009`, `pyscg-0010`, `pyscg-0012`, `pyscg-0013`, `pyscg-0023`, `pyscg-0019`, `pyscg-0050`, and `pyscg-0038`.
   - Read callers, registration points, and surrounding helpers until the input source and control path are visible.

2. Rebuild cross-module paths.
   - Track imports, exports, decorators, factory functions, dependency injection, task registration, and route registration.
   - Use module names, strings, SQL, log messages, and config keys as anchors when symbols are degraded.
   - Compare duplicate helpers or vendored copies to identify the live implementation.

3. Separate source facts from deployment assumptions.
   - Source can prove a hardcoded secret, unsafe deserializer, string-built command, or raw archive extraction.
   - Source may not prove whether a route is internet-exposed, a queue is attacker-writable, a process runs as root, or a config file is protected.
   - Keep missing deployment facts in `Open Questions / Assumptions`.

4. Validate Python behavior.
   - Confirm version-dependent behavior for bytecode, import resolution, archive APIs, exception semantics, thread pools, and optimized assertions.
   - Confirm whether recovery preserved the behavior relevant to the finding.

5. Build conservative PoCs.
   - Prefer a local harness that imports or reproduces the recovered function with harmless input.
   - State when the PoC uses reconstructed assumptions because the original entry point or environment is missing.
   - Do not claim remote exploitability unless the external input path is proven.

## Evidence And Reporting

For each confirmed finding:

- cite recovered file and line references when available
- state artifact provenance and recovery confidence
- show the input, missing control, sink, and impact in narrow code excerpts
- identify the exact missing runtime facts, if any, that affect severity but not root-cause confirmation
- include the primary OpenSSF rule and precise CWE mapping
- reference the per-finding PoC and state which steps were reconstructed versus executed

Use `Open Questions / Assumptions` for:

- missing entry-point registration
- unknown exposure or authentication boundary
- unknown OS user, container, filesystem, queue, or database permissions
- missing native extension or middleware behavior
- missing secret-management, deployment, or runtime configuration
- uncertainty introduced by decompilation or optimization

Use `Coverage` to state:

- artifact types reviewed
- packages and entry points reconstructed
- OpenSSF rule groups applied
- native/generated/configuration areas not available
- tests, dynamic validation, and PoC steps not executed

