From d5916e6a2079818666fde963cc65e3d73362dbca Mon Sep 17 00:00:00 2001 From: nikhil2004 Date: Sat, 26 Sep 2026 04:40:37 +0530 Subject: [PATCH] docs: correct factual drift in architecture and security policies (cherry picked from commit a61eeebb29f0ff20364890c94fe1013be5f7c3b5) --- ARCHITECTURE.md | 6 +++--- SECURITY.md | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 080f46f22..a3b1b5530 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -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. diff --git a/SECURITY.md b/SECURITY.md index 795454b21..3de3465c2 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -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 `` 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]`, `<>`, forged ``, 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