docs: correct factual drift in architecture and security policies

This commit is contained in:
nikhil2004 committed 2026-09-26 04:40:37 +05:30
1 parent c7fb720429
commit a61eeebb29
2 files changed
+9 -9

No files matched your search

+3 -3
View File
@@ -8,7 +8,7 @@ graphify is a Claude Code skill backed by a Python library. The skill orchestrat
detect() → extract() → build() → cluster() → analyze helpers → report.generate() → export.to_*()
```
Each stage lives in its own module and they communicate through plain Python dicts and NetworkX graphs - no shared state, no side effects outside `graphify-out/`. Most stages are a single function; `analyze.py` and `export.py` are sets of sibling functions rather than one entry point.
Each stage lives in its own module and they communicate through plain Python dicts and NetworkX graphs. While designed to minimize shared state, some stages (like extractors) rely on ambient module-level state around the active scan root. Most stages are a single function; `analyze.py` and `export.py` are sets of sibling functions rather than one entry point.
## Module responsibilities
@@ -87,7 +87,7 @@ All external input passes through `graphify/security.py` before use:
- URLs → `validate_url()` (http/https only) + `_NoFileRedirectHandler` (blocks file:// redirects)
- Fetched content → `safe_fetch()` / `safe_fetch_text()` (size cap, timeout)
- Graph file paths → `validate_graph_path()` (must resolve inside `graphify-out/`)
- Node labels → `sanitize_label()` (strips control chars, caps 256 chars, HTML-escapes)
- Node labels → `sanitize_label()` (strips control chars, caps 256 chars)
See `SECURITY.md` for the full threat model.
@@ -99,4 +99,4 @@ One test file per module under `tests/`. Run with:
pytest tests/ -q
```
All tests are pure unit tests - no network calls, no file system side effects outside `tmp_path`.
The test suite is designed to avoid network access and uncontrolled filesystem effects; most tests are isolated with temporary directories and environment fixtures.
+6 -6
View File
@@ -4,8 +4,8 @@
| Version | Supported |
|---------|-----------|
| 0.3.x | Yes |
| < 0.3 | No |
| Latest 0.9.x | Yes |
| < 0.9 | No |
## Reporting a Vulnerability
@@ -18,11 +18,11 @@ Report security issues via GitHub's private vulnerability reporting, or email th
- Potential impact
- Suggested fix (if any)
We will acknowledge receipt within 48 hours and aim to release a fix within 7 days for critical issues.
We will acknowledge receipt as soon as possible and work with you to release a coordinated fix.
## Security Model
graphify is a **local development tool**. It runs as a Claude Code skill and optionally as a local MCP stdio server. It makes no network calls during graph analysis - only during `ingest` (explicit URL fetch by the user).
graphify is a **local development tool**. It runs as a Claude Code skill and optionally as a local MCP stdio server. Its network boundaries are: AST/code extraction is local and deterministic; semantic extraction may send content to a configured model/backend; `ingest` uses explicit outbound fetch; HTTP MCP is an opt-in network listener.
### Threat Surface
@@ -32,12 +32,12 @@ graphify is a **local development tool**. It runs as a Claude Code skill and opt
| Oversized downloads | `safe_fetch()` streams responses and aborts at 50 MB. `safe_fetch_text()` aborts at 10 MB. |
| Non-2xx HTTP responses | `safe_fetch()` raises `HTTPError` on non-2xx status codes - error pages are not silently treated as content. |
| Path traversal in MCP server | `security.validate_graph_path()` resolves paths and requires them to be inside `graphify-out/`. Also requires the `graphify-out/` directory to exist. |
| XSS in graph HTML output | `security.sanitize_label()` strips control characters, caps at 256 chars, and HTML-escapes all node labels and edge titles before pyvis embeds them. |
| XSS in graph HTML output | `security.sanitize_label()` strips control characters and caps at 256 chars. (Note: HTML escaping happens separately in the HTML exporter, not in `sanitize_label()`). |
| Prompt injection via node labels | `sanitize_label()` also applied to MCP text output - node labels from user-controlled source files cannot break the text format returned to agents. |
| Prompt injection via source file content | During the semantic pass, source files are attacker-controlled text mixed into the LLM context. `_read_files()` in `llm.py` wraps every file in a hash-stamped `<untrusted_source path=... sha256=...>` delimiter block, the extraction system prompt instructs the model to treat that block as inert data and never as instructions, and `_neutralise_injection_sentinels()` defangs known chat-template/jailbreak tokens (`<\|im_start\|>`, `[INST]`, `<<SYS>>`, forged `</untrusted_source>`, etc.) before insertion. This is the table-stakes defense (issue #1210): it does not make injection impossible, but changes it from "works on first try" to "requires evasion." |
| YAML frontmatter injection | `_yaml_str()` escapes backslashes, double quotes, and newlines before embedding user-controlled strings (webpage titles, query questions) in YAML frontmatter. |
| Encoding crashes on source files | All tree-sitter byte slices decoded with `errors="replace"` - non-UTF-8 source files degrade gracefully instead of crashing extraction. |
| Symlink traversal | `os.walk(..., followlinks=False)` is explicit throughout `detect.py`. |
| Symlink traversal | `os.walk(..., followlinks=False)` is parameterized to avoid unchecked traversal where appropriate. |
| Corrupted graph.json | `_load_graph()` in `serve.py` wraps `json.JSONDecodeError` and prints a clear recovery message instead of crashing. |
### What graphify does NOT do