You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Harden SSH/API network security and bump to 1.0.19
Add shared URL validation helper (pybreeze/utils/network), route
AI code review and diagram download through it, disable redirect
following on requests.*, switch SSH/SFTP to WarningPolicy with
system host keys, and expand CLAUDE.md security checklist.
Copy file name to clipboardExpand all lines: CLAUDE.md
+44-5Lines changed: 44 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,6 +36,7 @@ pybreeze/
36
36
├── logging/ # pybreeze_logger
37
37
├── file_process/ # File/directory utilities
38
38
├── json_format/ # JSON processing
39
+
├── network/ # URL validation (SSRF prevention)
39
40
└── manager/package_manager/ # PackageManager class
40
41
```
41
42
@@ -95,25 +96,63 @@ All code must follow secure-by-default principles. Review every change against t
95
96
- Never use `subprocess.Popen(..., shell=True)` — always pass argument lists
96
97
- Never log or display secrets, tokens, passwords, or API keys
97
98
- Use `json.loads()` / `json.dumps()` for serialisation — never pickle
99
+
- Never use `yaml.load()` — always use `yaml.safe_load()`
98
100
- Validate all user input at system boundaries (file dialogs, URL inputs, network data)
101
+
- Handle exceptions without leaking stack traces, file paths, or internal state to the user
99
102
100
103
### Network requests (SSRF prevention)
101
-
- All outbound HTTP requests must go through `diagram_net_utils.safe_download_image()` or equivalent guards
102
-
- Only `http://` and `https://` schemes are allowed — block `file://`, `ftp://`, `data:`, `gopher://`
103
-
- Resolved IP addresses must be checked against private/loopback/link-local ranges (`ipaddress.is_private`, `is_loopback`, `is_link_local`, `is_reserved`)
- Never pass user-supplied URLs directly to `urlopen()` without validation
104
+
-**All** outbound HTTP requests to user-specified URLs must validate the target before connecting:
105
+
1. Only `http://` and `https://` schemes — block `file://`, `ftp://`, `data:`, `gopher://`
106
+
2. Resolve the hostname and check IPs against private/loopback/link-local/reserved ranges (`ipaddress.is_private`, `is_loopback`, `is_link_local`, `is_reserved`)
107
+
3. Enforce connection timeouts (default: 15 s for downloads, 30 s for API calls)
108
+
4. Enforce response size limits where applicable (default: 20 MB for binary downloads)
109
+
- Reference implementation: `diagram_net_utils._validate_url()` and `safe_download_image()`
110
+
- For API-style requests (`requests.get/post`): create or reuse a URL validation helper that performs scheme + IP checks, then call it before every `requests.*` call
111
+
- Disable automatic redirect following (`allow_redirects=False`) or re-validate the redirect target to prevent redirect-based SSRF
112
+
- Never pass user-supplied URLs directly to `urlopen()` or `requests.*` without validation
113
+
114
+
### Network requests (TLS / SSH)
115
+
- All HTTPS requests must use default TLS verification — never set `verify=False`
116
+
- SSH connections: `paramiko.AutoAddPolicy()` accepts any host key and is vulnerable to MITM. Document it as a known limitation in the SSH GUI. Prefer `paramiko.RejectPolicy()` or `paramiko.WarningPolicy()` when non-interactive verification is possible; at minimum, warn the user on first connection to an unknown host
117
+
118
+
### Subprocess execution
119
+
- Always pass argument lists to `subprocess.Popen` / `subprocess.run` — never `shell=True`
120
+
- Explicitly set `shell=False` for clarity in new code
121
+
- Never interpolate user input into command strings — pass as separate list elements
122
+
- Set `timeout` on all `subprocess.run()` calls to prevent hangs
123
+
- The IDE intentionally runs user-authored scripts; this is trusted local execution, not arbitrary remote code. Subprocess hardening protects against accidental shell injection, not against malicious local files
124
+
125
+
### JupyterLab integration
126
+
- The embedded JupyterLab server binds to `localhost` only and is intended for local development
127
+
-`--ServerApp.token=` and `--ServerApp.password=` are deliberately empty to enable seamless embedding — this is safe only because the server is localhost-only
128
+
- Do not change `--ServerApp.ip` to `0.0.0.0` or any externally-reachable address
129
+
-`--ServerApp.disable_check_xsrf=True` is required for the embedded QWebEngineView; do not expose the server externally with XSRF disabled
106
130
107
131
### File I/O
108
132
- File read/write paths from user dialogs (`QFileDialog`) are trusted (user-initiated)
109
133
- File paths loaded from saved data (`.diagram.json`) must be validated before access:
110
134
- Local paths: check `path.is_file()` and verify extension is in an allowlist
111
135
- URLs: pass through the same SSRF validation as user-entered URLs
112
136
- Never construct file paths by string concatenation with user input — use `pathlib.Path` with validation
137
+
- When writing to data directories (`.pybreeze/`), create the directory with `os.makedirs(exist_ok=True)` and always use `encoding="utf-8"`
138
+
- Never follow symlinks from untrusted sources — use `Path.resolve(strict=True)` and verify the resolved path is still within expected boundaries
113
139
114
140
### Qt / UI
115
141
-`QGraphicsTextItem` with `TextEditorInteraction` must not be enabled by default — use double-click-to-edit pattern to prevent unintended text selection issues in themed environments
116
142
- Plugin loading (`jeditor_plugins/`) uses auto-discovery — only load `.py` files, skip files starting with `_` or `.`
143
+
-`QWebEngineView.setUrl()` must only load trusted URLs (localhost or user-confirmed external URLs) — never load untrusted HTML or URLs without user consent
144
+
- Never call `QWebEngineView.setHtml()` with unsanitised content — this enables XSS within the embedded browser
145
+
146
+
### Secrets and credentials
147
+
- SSH passwords and private key passphrases are held in memory only during the session — never persist to disk or logs
148
+
- Password fields must use `QLineEdit.EchoMode.Password`
149
+
- API endpoint URLs may contain embedded tokens — treat URL strings with the same care as credentials (do not log full URLs)
150
+
- Environment variables (`PYBREEZE_LOG_MAX_BYTES`, etc.) must never contain secrets; use dedicated secure stores for credentials
151
+
152
+
### Dependency security
153
+
- Pin dependencies to exact versions in `requirements.txt` / `dev_requirements.txt`
154
+
- Do not add new dependencies without reviewing their security posture (maintained? known CVEs?)
155
+
- Avoid transitive dependency bloat — prefer stdlib solutions when the alternative is a single-function dependency
0 commit comments