Commit Graph

10 Commits

Author SHA1 Message Date
Martin Vogel 673e523879 fix(security-strings): audit .mcpb manifests as structured text, not as binaries
The v0.10.3 release failed its `verify` gate:

    --- Auditing: scan-...--manifest.json ---
    BLOCKED: Unauthorized URL in binary: https://github.com/DeusData
    BLOCKED: Unauthorized URL in binary: https://deusdata.github.io/...
    === BINARY STRING AUDIT FAILED ===

The blocked URLs are OURS — the .mcpb bundle manifest's own homepage and
documentation fields.

security-strings.sh already knows that URL and dangerous-command auditing are
"designed for compiled artifacts" and skips them for text, keeping the
credential and base64 audits that are universally meaningful. Its detection
just had no case for JSON: `file` reports "JSON data", which matched none of
the shell-script/ASCII-text patterns, so a manifest was audited as if it were a
compiled binary. An MCP manifest is exactly the shape that misfires — it
carries project URLs by design, and a `command` field by specification.

This is the first release to ship .mcpb bundles, which is why it surfaced now:
it is the first time a manifest reached the scanned object set. The bundles
were noted as end-to-end unproven until a stable release; this is that proof
doing its job.

Two changes:
- Classify structured-text artifacts by extension FIRST (.json/.yaml/.toml/
  .md/...), then by `file` type with JSON/XML added. The extension check also
  covers hosts without file(1), where the existing `command -v` guard silently
  left every artifact classified as binary.
- Allow-list our own org root and documentation site, so a compiled binary
  embedding the docs link (the graph UI does) passes on its own merits rather
  than relying on the text exemption.

Tests: the manifest case, plus a control proving the exemption is narrow — the
credential audit still runs on structured text. The existing negative control
(an unauthorized URL in a real binary is still BLOCKED) is unchanged and still
passes, so the binary audit is not weakened.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-12 20:57:43 +02:00
Martin Vogel 170d5a82ab fix(ci): allow-list MSYS2 toolchain URL in binary string audit
The MSYS2 CLANG64 toolchain bakes its package-tracker URL
(https://github.com/msys2/MINGW-packages) into the static Windows .exe via
libc++/compiler-rt. The Layer 2 binary string audit flagged it as an
unauthorized URL, failing smoke-windows (both the standard and ui variants)
while Linux smoke stayed green. Add it to ALLOWED_URLS alongside the other
compiler/linker toolchain URLs (gcc.gnu.org, sourceware.org, launchpad).

Add tests/test_security_strings_allowlist.sh as a reproduce-first regression
guard: it reproduces the BLOCKED failure with a binary fixture and includes a
negative control proving a genuinely unauthorized URL is still rejected. Wired
into scripts/test.sh as Step 6.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-24 03:15:36 +02:00
Martin Vogel 3305c1f9d3 fix(security): widen release audit to all files in binaries/
Previously the verify job only ran scripts/security-strings.sh on
files matching binaries/codebase-memory-mcp* — install.sh, install.ps1,
LICENSE, and any future companion files in the release archives were
NOT covered by the binary-string audit (only by VirusTotal).

Changes:
- release.yml: loop over binaries/* (every file in the audit set).
- security-strings.sh: detect file type via 'file -b'. For shell
  scripts and other text files, skip the URL audit and dangerous-cmd
  audit (those rules are tuned for compiled binaries — install.sh
  legitimately uses wget as a curl fallback, and 'case https://*)'
  globs look like unauthorized URLs to a strings dump). Always run
  credential and base64 pattern audits — those are universally
  meaningful regardless of file type.
- Verified locally: install.sh and install.ps1 now both pass.

Net effect: every release artifact is now audited, with rule sets
appropriate to its file type.
2026-05-05 00:59:58 +02:00
Martin Vogel 72c5bdba89 fix(security-strings): allowlist 'telnet' from rst grammar URI schemes
The rst tree-sitter grammar (added in the 89-grammar bump) contains a
valid_schemas[] array listing URI schemes (http, https, ftp, mailto,
telnet, ssh) in vendored/grammars/rst/tree_sitter_rst/chars.c. The
'telnet' string ends up in the binary's string table and tripped the
dangerous-command detector, blocking smoke on every platform.

Add an allowlist mechanism for known-benign matches with a comment
pointing at the source file, so future false positives can be
documented the same way.
2026-05-04 22:04:39 +02:00
Martin Vogel 6f268d0f91 Respect nested .gitignore files during indexing, security audit all variants
Nested .gitignore support (fixes #178):
- Load per-subdirectory .gitignore during walk, match paths relative to
  the gitignore's directory via local_rel_path()
- Root and nested gitignores stack independently
- Owned gitignores collected and freed at walk end (avoids use-after-free
  from borrowed pointers on the iterative stack)

Security:
- Run security-strings/install/network + ClamAV + Windows Defender on
  ALL binary variants (standard + UI), not just standard
- Whitelist UI bundle URLs (React, Three.js, Google Fonts, Tailwind, W3C)

Co-Authored-By: dLo999 <dLo999@users.noreply.github.com>
2026-04-06 19:44:16 +02:00
Martin Vogel 9e1e30ded0 Allow toolchain URLs in binary string audit (static build artifacts)
gcc/glibc embed bug tracker URLs (bugs.launchpad.net, gcc.gnu.org,
sourceware.org) into statically-linked binaries. These are compiler
artifacts, not our code.
2026-04-06 17:47:04 +02:00
Martin Vogel 8967d7cd41 Remove AV-triggering words from token vocabulary, revert audit allowlist
Strip 11 tokens (wget, curl, netcat, ncat, telnet, passwd, shadow,
exploit, hack, inject, malware) from Nomic vocabulary. These fall back
to sparse random vectors — negligible quality impact. Removes all
security audit exceptions: zero allowlists, zero suppressions.
2026-04-06 16:12:02 +02:00
Martin Vogel 3f7f7eeab7 Fix binary string audit: exclude bare token vocabulary matches
The embedded Nomic code token vocabulary (40K tokens) includes words like
"wget" as code tokens. Filter out bare single-word matches (2-10 lowercase
chars) since real dangerous strings appear in command context, not as
standalone vocabulary entries.
2026-04-06 15:40:11 +02:00
Martin Vogel 93d332d1e0 Fix security audit false positives in CI
- UI audit (L6): allowlist bundled framework URLs in dist/ (React error
  URLs, W3C namespace URIs, Three.js credits, Google Fonts, Tailwind).
  These are embedded by npm deps during Vite build, not our code.
- Binary strings (L2): skip URLs shorter than 15 chars — Windows binary
  has byte sequences that strings(1) interprets as "https://H9" etc.
- Allow Google Fonts <link> in HTML (loaded by index.html for Inter/
  JetBrains Mono fonts).
2026-03-20 18:47:55 +01:00
Martin Vogel cd1417427c Add 8-layer security test suite + hardening
Code-level defenses:
- cbm_validate_shell_arg(): reject shell metacharacters before popen/system
- SQLite authorizer: block ATTACH/DETACH at engine level
- CORS localhost-only origin reflection (replaces wildcard *)
- Path containment: realpath() check in get_code_snippet
- process-kill restricted to server-spawned PIDs
- SHA256 checksum verification in update command

Security audit scripts (8 layers):
- L1: Static allow-list for dangerous calls + URLs
- L2: Binary string audit (URLs, payloads, credentials)
- L3: Network egress monitoring via strace (Linux)
- L4: Install output path + content validation
- L5: Smoke test hardening (clean shutdown, residual procs)
- L6: Graph UI audit (external domains, CORS, binding)
- L7: MCP robustness (23 adversarial JSON-RPC payloads)
- L8: Vendored integrity (checksums + dangerous call scan)

CI: parallel security-static job (no build needed), binary
layers in smoke jobs per-platform. Cleanup of test fixture
dirs in clean.sh + .gitignore.
2026-03-20 18:19:15 +01:00