Skip to content

Security: macitch/StrucIn

Security

SECURITY.md

Security Policy

Supported Versions

Version Supported
0.1.x development line (latest source checkout) Yes

StrucIn has not yet been published on PyPI. Fixes listed under Unreleased in CHANGELOG.md require an updated source checkout; older copies do not acquire those fixes automatically.

How StrucIn Handles Your Code

StrucIn analyzes Python source without importing or executing the target project:

  • It reads Python files and parses their AST.
  • Commands write or replace generated JSON, Markdown, and dashboard files.
  • StrucIn-managed cache files are stored in .strucin_cache/ within the target repository.
  • Normal repository commands remove expired configured outputs and cache files before running. [lifecycle] cache_retention_days defaults to 14 and applies to both outputs and caches. Keep archival snapshots at separate paths.

Normal-mode analysis and dashboard exports contain identifiers, paths, and docstrings. Semantic indexes also store source/document chunks alongside their vectors. Treat those files as repository content when deciding what to share; use safe mode for anonymized exports.

Source and Documentation Links

Python and documentation discovery skips file links that resolve outside the selected repository, dangling links, symlink loops, and non-regular files. Links to regular files inside the repository remain supported, with their repository-relative link paths preserved in analysis and search results. Directory links are not traversed during discovery.

Containment is rechecked whenever source or documentation bytes are read. On platforms supporting descriptor-relative opens and O_NOFOLLOW, path components are opened without following links to reject replacements between validation and reading. Other platforms use the validated canonical path. A file that becomes unsafe after discovery aborts that run instead of contributing outside content.

Search indexes produced before this policy are rebuilt by the CLI. Existing exports are not retroactively scrubbed; regenerate any previously shared analysis, reports, or indexes that may have included outside links.

Artifact Destinations

Configured outputs and StrucIn-managed caches must stay within the target repository. Parent-directory segments (..) and symlinks that resolve outside that directory are rejected before writing or cleaning up artifacts. All configured destinations are checked before cleanup deletes any stale files.

The explicit web --out /path/to/export option selects a separate dashboard output directory. Generated dashboard files are confined to that selected directory.

LLM Integration (Optional)

explain can call a provider when its SDK is installed and its API key is present in the process environment. Anthropic is checked first, then OpenAI. A cached result can avoid the call; unavailable providers or failed requests use the local template fallback. No separate confirmation is requested before a provider call.

The JSON context is truncated to 12,000 characters, in addition to the prompt text. In normal mode it can include the repository root, file paths, module names, dependency cycles, metrics, and module docstrings. Whole source files are not uploaded, but docstrings can themselves contain code examples or sensitive text.

Recognized secret patterns in docstrings are redacted before forming that context. Pattern matching is best effort, not a general guarantee that all secrets are removed from arbitrary content or identifiers. Safe mode omits docstrings and anonymizes identifiers before any provider call.

Neural Search and Local Serving

The optional embedding backend runs SentenceTransformer.encode locally. Loading a model can download files and use the library's own cache outside the repository; StrucIn's artifact containment and retention rules do not manage that cache. Set [search] embedding_model = "hashing-v1" to avoid loading or downloading a neural model. Safe mode alone does not disable model loading.

The dashboard server defaults to 127.0.0.1 and has no authentication or TLS. It serves the selected output directory, so use a dedicated directory and keep the loopback binding for local use. Binding to a network interface exposes its contents to machines that can reach that address.

Safe Mode

Enable safe mode for a repository with:

[security]
safe_mode = true

scan, analyze, report, explain, search, and web honor this setting. Each also accepts --safe-mode or --no-safe-mode to override it for one run. Pre-commit hooks honor the repository setting. diff operates on snapshots without loading repository configuration; use diff --safe-mode explicitly.

In safe mode:

  • Generated index, analysis, graph, report, narration metadata, and dashboard contents hide repository paths, file paths, module/package names, import names, and class/function names. Graph relationships and numeric metrics remain.
  • All docstrings and source snippets are omitted from shareable data. LLM context is anonymized before the provider call, including the repository root. Known identifiers and recognized secret patterns are filtered again from provider responses and cached narration before writing or returning them.
  • Raw analysis caches are neither read nor written. Narration uses a separate .strucin_cache/explain_safe_cache.json containing filtered content. Normal explanation caches are never reused by safe mode.
  • Search rebuilds its index in memory on every run, without reading or writing semantic_index.json. Results retain scores and line numbers with anonymous labels; source text and the query are omitted from displayed output.

Anonymous labels are scoped to an export and can change when the file set changes. For accurate comparisons, run diff --safe-mode on the original snapshots so matching happens before anonymization.

Safe mode governs newly generated content; it does not retroactively scrub older artifacts or caches. Existing retention cleanup still applies. Output filenames, configuration files, and diagnostic errors are not anonymized, so share the intended generated artifacts rather than the entire working directory or logs. Structural metrics and graph topology remain visible.

Library callers must pass safe_mode=True to the relevant output writer, report generator, explainer, or dashboard builder. Raw analyze_repository results remain in memory with original names; use use_cache=False to prevent raw cache reads and writes. The low-level semantic index writer persists source text and should not be used for a safe export.

Dependency Security

Security minimums are declared for dependencies identified by the September 2026 audit, including transitive packages that an existing environment could retain:

Package Minimum Reason
Pygments 2.20.0 CVE-2026-4539
setuptools 83.0.0 CVE-2026-59890, plus earlier package-index fixes
PyTorch (embedding extras) 2.13.0 CVE-2025-3000
pytest (development) 9.0.3 CVE-2025-71176

Use pip 26.2 or newer when refreshing an existing environment. Dependency audits run on pull requests, pushes to main, and manual workflow dispatches. They check fresh resolutions and explicit direct minimum versions against current PyPI advisories; see the audit instructions.

Advisories identify affected package versions, not proof that StrucIn exposes the affected code path. A passing audit covers the scanned versions and known advisories at that time. Model weights, live providers, and arbitrary pre-existing environments require separate validation.

Reporting a Vulnerability

If you discover a security vulnerability in StrucIn, please report it responsibly:

  1. Do not open a public GitHub issue.
  2. Email contact@macitch.dev with:
    • A description of the vulnerability
    • Steps to reproduce
    • Affected version(s)
  3. You will receive an acknowledgment within 48 hours.
  4. A fix will be prioritized and released as a patch version.

Scope

The following are in scope for security reports:

  • Secret leakage through LLM calls or output artifacts
  • Path traversal in file scanning or artifact writing
  • Code execution through crafted Python files (AST parsing should never execute code)
  • Dependency vulnerabilities in the documented base and optional dependencies

The following are out of scope:

  • Denial of service through extremely large repositories (expected behavior)
  • Issues requiring physical access to the machine running StrucIn

There aren't any published security advisories