CodeInspectus, by Synvoya
[License: Apache 2.0]
[Node.js]
[npm downloads]
[MCP-ready]
[Local-first]
[No telemetry]
[Official MCP Registry]
[codeinspectus MCP server]
[GitHub stars]
A local-first, privacy-preserving security MCP server and CLI. Any AI coding agent
(Claude Code, Cursor, Codex, Windsurf, Cline, Aider) can invoke CodeInspectus to
scan AI-generated / "vibe-coded" code for real vulnerabilities, map findings to
compliance frameworks as honest code-level coverage, and drive a scan → fix →
rescan loop — fully on your machine, with no account and zero network
egress at scan time.
[CodeInspectus demo]
Reproduce the V2.1 proof: the [email protected] package scans an immutable public Rich
commit, finds one high-confidence GitHub Actions expression-injection pattern, applies GitHub's
documented intermediate-env remediation in a temporary clone, confirms it as 1 resolved,
0 remaining, 0 introduced, 0 not rechecked, then creates and verifies sealed evidence for both
states. Run the reproduction script or read the
scanner-derived case study. The recorded
pre-publication run used the exact V2.1 tarball; the script defaults to npm after publication.
The case uses the ai scanner class to isolate stable native behavior; use a normal full scan for
broad repository coverage.
If CodeInspectus is useful, star the repository
so other AI-app builders can find it.
CodeInspectus orchestrates four best-in-class OSS engines behind one normalized,
CWE-keyed schema, and adds its own AI-code-specific checks that generic
scanners miss:
- Opengrep — SAST / OWASP Top 10 (SARIF)
- Gitleaks — secrets
- Trivy — dependency CVEs (SCA), IaC misconfig, secrets, SBOM, and licence findings when you opt in (
include_licenses: true / --licenses; off by default)
- osv-scanner (Google) — offline dependency matching against OSV.dev data, including
OpenSSF malicious-package (
MAL-) advisories. It runs only on the OSV databases you approved
for the ecosystems your repository uses
- Synvoya (CodeInspectus) — an offline gap-advisory layer for what those engines miss:
declared Node.js, PHP, Python, Ruby, Go, .NET and Java versions (version-manager pins, manifests,
CI setup steps, image tags), end-of-life lines, exploited products such as Adobe Commerce and
WordPress core, malicious package versions, vendored and CDN-loaded JavaScript libraries (checked
by osv-scanner through a per-scan SBOM), Magento editions, the declared Go toolchain, and GitHub
Actions advisories. It reads only what the repository declares, ships inside the package with
SHA-256 integrity checks, and folds into an upstream finding rather than duplicating it. Synvoya also
provides the PHP and Node.js Opengrep rule packs (
syn-php-*, syn-node-*). See
docs/SYNVOYA.md
- CodeInspectus Pub — first-party, exact-version Dart/Flutter dependency matching and
CycloneDX/SPDX inventory from
pubspec.lock, backed by a bundled offline OSV Pub snapshot
- CodeInspectus native checks — client-side secret/bundle exposure, Supabase
RLS / inverted-auth (the CVE-2025-48757 class), prompt-injection sinks,
model-produced tool arguments reaching Node, Python, or narrowly supported Go, Java, C#, PHP, Rust, and Ruby shell sinks without a visible guard,
general model output reaching JavaScript
eval/Function or import-proven shell-string APIs,
conventional Next.js and import-proven Express admin API handlers missing visible authentication
or server-side authorization, Supabase Edge Functions with explicit anonymous deployment but no
request authentication or privileged-operation authorization,
client-writable user_metadata authorization, and unsanitized model/user output
rendered via dangerouslySetInnerHTML (XSS / LLM05), plus explicit API-boundary
leaks, raw request-to-database writes, sensitive logging, and evidence-gated
security-header/CSP/Referrer-Policy/Permissions-Policy/session-cookie/Supabase-CAPTCHA
configuration checks. Separate
first-party packs cover six narrow Flutter/Dart source failure modes and eight bounded
Android/iOS repository-configuration failures, plus four React Native and two Expo
framework-specific mobile failures. A bounded Python AI/API pack covers ten narrow
Django, Flask, FastAPI, Starlette, Jinja, OpenAI, Anthropic, LangChain, and OS-command source failures.
Separate Go, Java, and C# AI packs each contribute one exact official OpenAI SDK
tool-argument-to-shell rule; the PHP pack contributes one equivalent rule for the
community-maintained openai-php/client ecosystem, and the Rust pack contributes one
bounded rule for the community-maintained async-openai ecosystem. A Ruby pack contributes one
equivalent rule for the exact official openai gem. A Firebase configuration pack contributes
three literal public-write rules for Firestore, Cloud Storage, and Realtime Database. A GitHub
Actions pack contributes two workflow rules for direct untrusted-context shell interpolation and
exact pull_request_target checkout-and-execute chains.
The shipped manifest contains 126 curated detections: 72 first-party native rule
IDs (29 JavaScript/TypeScript, 6 Flutter/Dart, 4 Android, 4 iOS, 4 React Native, and
2 Expo, plus 10 Python AI/API, 1 Go AI, 1 Java AI, 1 C# AI, 1 PHP AI, 1 Rust AI, 1 Ruby AI,
3 Firebase configuration, 2 GitHub Actions workflow, and 2 JavaScript baseline SAST rules), 18 Opengrep-owned
SAST rules, 19 Synvoya PHP Opengrep rules (syn-php-*), 12 Synvoya Node.js Opengrep rules
(syn-node-*), and 5 custom Gitleaks rules. All 20
ci-baseline-* Opengrep YAML rules remain physically active:
the two native-owned rules reconcile exact results and fall back to Opengrep on mismatch or
native unavailability. Opengrep, Gitleaks, Trivy, and osv-scanner are optional, managed, additive engines.
CodeInspectus explains each engine's coverage, license, platform-specific size, and required
action before asking permission. After approval it downloads the official, SHA-pinned
engine binaries, stores them outside the npm package, and calls
them as local subprocesses. It does not fork them.
Why CodeInspectus?
AI-generated apps often ship with security mistakes that generic scanners miss: exposed
client-side secrets, weak Supabase auth patterns, unsafe HTML rendering, prompt-injection
sinks, and risky AI/vector-store integrations.
CodeInspectus combines proven local scanners with AI-app-specific rules, then exposes the
workflow through an MCP server so coding agents can scan, explain, and help fix issues
before shipping.
Install
Prerequisite: Node.js ≥22. Node 24 LTS is recommended. No separate engine or Cosign
installation is required. CodeInspectus can bootstrap a SHA-pinned Cosign verifier inside
~/.codeinspectus/ after approval; signature verification remains fail-closed.
On Linux, the current upstream Opengrep assets require glibc. Alpine/musl remains supported for
native CodeInspectus rules, Gitleaks, and Trivy, but setup marks Opengrep unavailable before any
download and reports aggregate scan coverage as partial when it is selected.
The official @contentauth/c2pa-node validator is an optional peer because its upstream package
downloads a platform-native binding during its own lifecycle script. Normal CodeInspectus installs
do not install that peer. Install it explicitly alongside CodeInspectus when local C2PA validation
is required; otherwise candidate assets report partial content_provenance coverage.
On a terminal, a first bare npx codeinspectus run opens this guided setup. MCP clients continue
to start over piped stdio and expose codeinspectus_setup: agents must request a plan, show it,
ask permission, then call install with confirm_downloads=true. Declined choices are saved so
users are not repeatedly prompted; setup --reset clears them.
Setup first checks local state without network access. It downloads only missing,
mismatched, or newly pinned binaries, verifies them against the immutable lockfile shipped in the
npm package, and atomically installs them under ~/.codeinspectus/. It refreshes the offline
Trivy vulnerability DB only when it is missing, lacks rescan provenance, or is more than seven
days old. Rule-only CodeInspectus upgrades therefore download nothing. After setup, scans
perform zero network I/O.
osv-scanner's vulnerability data is one OSV database per package ecosystem. Setup downloads a
database only after you approve it, only for the ecosystems your repository's lockfiles name
(--path, or the path the MCP setup tool takes) or the ones you list with --osv-ecosystems, and
only from osv-vulnerabilities.storage.googleapis.com. The allow-list is language ecosystems: npm,
PyPI, Packagist, Go, crates.io, RubyGems, Maven, NuGet, and Pub, plus the small "GitHub Actions" database
(about 100 KB, offered when the repository has workflows) that Synvoya's Actions matcher reads. Distribution
ecosystems are never downloaded. The npm database is over 200 MB zipped, so setup shows each size before you approve.
OSV publishes no signature for these files; integrity is TLS to that one host plus a SHA-256
CodeInspectus records at install time. Setup (unless you declined osv-scanner) and a bare
repair-engines (while osv-scanner is installed) also refresh an OSV database you already
installed once it is more than seven days old or has lost its install record; neither adds an
ecosystem you did not approve. To add a database later:
npx codeinspectus repair-engines osv-scanner --osv-ecosystems PyPI.
Every scan and codeinspectus_list_rules response includes structured engine_setup state:
ready, repair_required, db_refresh_recommended, or unsupported_platform. MCP agents are
instructed to explain non-ready state and obtain approval through codeinspectus_setup. There is
no silent npm postinstall download. repair-engines remains available for advanced/manual use;
the older install-engines command remains a compatibility alias.
If a Trivy DB was installed before 0.3.2, scan output tells your agent that CVE rescan
tracking is not yet enabled. The agent should run setup (codeinspectus_setup, or npx codeinspectus setup)
once; this re-fetches the DB through the verified install path and records its provenance.
Until then, vanished CVEs conservatively report not_rechecked; current scan findings
remain complete and unaffected.
Re-verify your pinned binaries any time:
CLI, CI, and local evidence workflows
Git-scoped scans retain full repository context, tag changed versus supporting-context
findings, and report exact resolved revisions and explicit completeness limits. They never
checkout, reset, stage, or modify the repository. See
docs/GIT-SCOPED-SCANS.md.
Sealed bundles retain redacted JSON, SARIF, Markdown, coverage, provenance and an additive
canonical scan record with content hashes for every artifact. Verification is mandatory before
bundle export or comparison. See docs/SEALED-SCAN-BUNDLES.md.
CSV is a deterministic spreadsheet-safe projection of the canonical JSON model. It always retains
an explicit scan/coverage row, even with zero findings, and neutralizes formula-triggering cells.
See docs/CSV-EXPORT.md for the stable column contract.
The V2 TypeScript SDK is available from codeinspectus/sdk. It is a bounded,
shell-free wrapper around the exact installed local CLI and exports versioned finding, coverage,
history, baseline, triage and bundle types without duplicating scanner logic. See
docs/TYPESCRIPT-SDK.md.
Bulk mode scans already-existing repositories under one explicit local parent with bounded
concurrency, per-repository isolation and an atomic resumable manifest. It never clones or requires
a GitHub account. See docs/BULK-SCANNING.md.
Repository-history mode is separately opt-in and requires exact revision, UTC date and commit-count
bounds. It scans isolated immutable snapshots, marks shallow or truncated history partial, and never
describes an old finding as current or a historical secret as active. See
docs/REPOSITORY-HISTORY.md.
Issue adapters generate one redacted, review-required GitHub, Jira or Linear JSON payload without
authentication or submission. Destination visibility is mandatory and public/private disclosure
warnings remain in the artifact. See docs/ISSUE-PAYLOADS.md.
The first command is report-only: findings are retained but do not fail complete scans. The second
enforces a severity threshold. Both fail closed with exit 2 when aggregate coverage is partial or
unknown; coverage takes precedence over finding severity. Exit 1 is reserved for threshold findings
after complete coverage. See the CLI command reference and
CI policy and SHA-pinned GitHub Actions workflow
for the full exit contract, SARIF upload, artifact privacy, and fork/Dependabot behavior.
Two options shape what a scan reports. Licence findings are off by default since 4.0 (they are
informational and none is fixable); --licenses (MCP include_licenses: true, SDK includeLicenses)
turns them on, and a scan without them carries an informational coverage note. --accept-gaps
(MCP accept_gaps) names declared coverage gaps you accept so that they alone do not fail CI; the
gap stays listed and coverage still reads partial. Gap ids are in
CI policy.
Baseline enforcement fails only on findings proven new against a compatible explicit stored scan.
Incompatible, partial, or unknown comparison evidence fails closed with exit 2. Local triage adds
append-only review context without hiding or changing findings. See
baselines and local triage for commands, exact matching, bounds,
storage, redaction, schemas, and audit behavior.
Local scan history can be listed, inspected, rerun, and compared without network access:
Comparison is evidence-gated: absence is Resolved only after compatible producer components and
complete like-for-like coverage; otherwise it is Not rechecked / unknown. See the
scan history and comparison contract for filters, bounds, V1.x compatibility,
corruption handling, and Reopened provenance.
The shipped agent rules also define an approval-gated
one-finding remediation workflow: investigate one exact finding,
propose the regression and smallest patch, edit only after separate approval, test, then rescan
against the exact prior scan. Only a CodeInspectus resolved result supports a scanner-resolution
claim; not_rechecked remains an explicit proof gap.
Two explicit, optional workflows extend investigation without changing scanner truth:
- Threat-model and knowledge-base review treats every
repository-controlled document as untrusted context. Documents can explain or prioritize raw
findings, but never suppress, downgrade, override, or mark them resolved.
- Bounded multi-agent review keeps deterministic findings and agent
interpretations in separate evidence lanes, applies explicit agent/time/scope/cost limits, and
requires an exact-prior deterministic rescan before any scanner-resolution claim.
These rules are included in the npm package under agent-rules/; normal CLI and MCP scans do not
load documents, invoke models, or depend on either workflow.
An MCP server is installed once per machine and shared across all your
projects — it is not a per-repo npm install dependency.
Client registration
The server command is the same across clients, but each client uses its own
configuration format. Clients with JSON MCP configuration use:
For Codex, choose one registration method:
- Codex app or IDE extension: open Settings → MCP servers → Add server,
choose STDIO, set the command to
npx and arguments to -y,
codeinspectus, then restart.
- Codex configuration file: add this to global
~/.codex/config.toml or a
trusted project's .codex/config.toml:
Codex defaults MCP tool calls to 60 seconds. CodeInspectus runs multiple security
engines concurrently and permits up to five minutes per engine, so 600 seconds
avoids premature client timeouts on larger repositories. This is a Codex client
timeout only; it does not change engine limits or other clients' configurations.
Optional: drop in the ready-made agent-rules/ so your agent
auto-runs the scan → fix → rescan loop.
MCP clients that support server instructions, including Codex, also receive the
safe workflow automatically: show findings first, obtain granular approval before
fixes, and rescan before claiming an issue is resolved. The agent-rule files remain
useful when you want the same policy persisted explicitly in a repository.
Tools
CodeInspectus scans, plans and reports without repository mutation. The only source/repository
mutation surfaces are the explicitly approved V3.3 apply/rollback tools. It stores engine data,
scan history, cleanup checkpoints and content-free audit records under ~/.codeinspectus.
codeinspectus_generate_sbom can also write an optional SBOM to a managed directory by default,
or to an absolute .json path you choose; it refuses to replace any existing file that is not
already an SBOM. Git runs only in read-only mode with command-line overrides, so a scanned
repository's own config cannot make a scan run programs (fsmonitor hooks, signature programs, or
filter drivers) or rewrite .git/index.
Each scan also reports a read-only git-safety state: if there's no git repo or
uncommitted changes, it recommends creating a checkpoint before fixes — your agent
runs git only with your approval; the tool never runs git commands that change your repository.
Source Integrity — V3.1
V3.1 activates the first capability in the stable, non-CWE repository_trust contract across scan,
rescan, CLI JSON, MCP structured output, SARIF metadata, and the TypeScript SDK. It deterministically
inspects supported repository text for bidirectional overrides/unbalanced controls, zero-width or
default-ignorable token characters, concealed Unicode tag sequences, encoded variation-selector
runs, and a bounded set of mixed-script identifier confusables.
Every artifact reports escaped code points, Unicode names, exact file/line/code-point column,
UTF-8 byte offset, context classification, validator identity, confidence, limitations and an
approval-required proposed action. Very long tag/variation runs retain the exact span and sequence
length while capping rendered evidence to 64 code points; dense candidates and identifiers are
bounded before output materialization and incomplete work is reported as partial. Initial BOMs,
legitimate RTL text, emoji variation/ZWJ/tag
sequences, international-language joiners and ambiguous confusables are suppressed or kept
non-destructive. Scans never edit files. V3.3 cleanup requires an exact plan, explicit approval for
the named file and marker, a recoverable checkpoint, the smallest supported edit, tests, and a rescan.
This is source-integrity protection, not AI-authorship detection. V3.2's explicit-attribution
and C2PA results are separate capability records; hidden Unicode is never promoted into either.
CodeInspectus does not claim that hidden Unicode is a Claude watermark or evidence of AI generation.
AI Provenance Audit — V3.2
V3.2 activates two more read-only repository_trust capabilities:
explicit_ai_attribution deterministically inspects bounded source/config headers, local git
commit trailers, and supported image EXIF/XMP/IPTC/PNG metadata for explicit AI-generator or
AI-source declarations. These are verified observations of declarative records—not proof that
the statement is truthful, proof of vendor origin, or a statistical authorship judgment.
content_provenance uses the optional official Content Authenticity Initiative Node validator
to inspect supported local C2PA Content Credentials. Results distinguish valid, trusted, invalid,
present-but-inconclusive, and remote-reference evidence. Offline scans never fetch a remote
manifest, OCSP response, trust list, or revocation endpoint.
Every parser and traversal path is bounded, rejects symbolic links, and reports exclusions as
partial. V3.2 detection remains read-only. Git-history, legal, licensing and compliance records
remain protected; verified non-protected artifacts can enter V3.3's separately approved workflow.
V3.2 does not remove metadata, rewrite text, inspect pixels/audio/video frames, or claim that absence
of a marker means human authorship. Statistical text-watermark
verification remains unavailable until an authoritative, independently verifiable detector with
calibrated operating thresholds is available.
Verified Repository Cleanup — V3.3
V3.3 adds three MCP tools: codeinspectus_plan_cleanup, codeinspectus_apply_cleanup, and
codeinspectus_rollback_cleanup. Planning always runs a fresh repository-trust audit and accepts
only exact verified artifact IDs. It rejects changed, ambiguous, protected, unsupported, duplicate,
or over-broad scope and records SHA-256 preimages plus the exact transformation before approval.
Apply requires the ready plan ID, the identical artifact-ID set, confirm_cleanup=true, and a
separate rights confirmation for attribution or provenance. Text cleanup is limited to exact
verified UTF-8 ranges and standalone attribution comments. It creates a managed content backup,
uses atomic replacement, reruns the same validators, and emits a content-free audit record.
Before the first write it verifies every preimage, computes every output, and persists all backups
plus a content-free journal, so an apply interrupted at any point can be rolled back after a
restart; new planning for that repository is blocked, naming the cleanup ID, until it is reviewed.
Rollback restores only when post-clean bytes still match the recorded result; it refuses to
overwrite later user changes and never touches anything if one file changed.
Supported media adapters create a new *.codeinspectus-clean.* copy and preserve the original.
They strip hard-bound metadata containers from PNG, JPEG, MP3, WAV, MP4, MOV, M4A and M4V assets
without changing encoded image, audio, or video payloads; ISO BMFF chunk offsets are rewritten so the
copy still plays, and fragmented or externally indexed MP4/MOV files are refused. Image metadata
artifacts come from the built-in parser; audio and video assets become eligible only through C2PA
artifacts reported by the optional official validator. Container-level removal
must be acknowledged because unrelated metadata in the selected container can also be removed.
C2PA cleanup requires a separate provenance-copy acknowledgement. The cleaned copy is scanned
independently; the original evidence-bearing asset remains untouched.
CodeInspectus does not run arbitrary repository commands. The result therefore marks repository
tests, formatters and builds as not_run and required; the calling coding agent must run the
relevant checks before presenting cleanup as complete. V3.3 never rewrites Git history, removes
visible logos, changes pixels/frames/audio, detects statistical watermarks, or claims human authorship.
See the V3 migration guide for schema and SDK changes.
detected_technologies explains the bounded repository signals CodeInspectus saw.
pack_coverage separately reports how many registered native analyzers and rules actually ran.
A pack state of ran means those listed rules executed; it is not a claim of complete security
coverage for the named language or framework. Native JavaScript/TypeScript packs read files with a full parser
(@babel/parser) and report a file they cannot parse as the gap native-parse-errors; their rules are
intrafile patterns with no type checker or data flow, so code written to avoid a pattern can avoid it.
When the SAST scanner runs, Opengrep's parser still scans the same files for generic sinks. not_applicable means the installed pack did not match detected project technology; not_run, partial, and unavailable distinguish scanner
filtering from incomplete or failed execution. The Flutter pack runs only when bounded repository
signals identify Flutter; an ordinary Dart package does not activate it. Android and iOS packs
likewise require bounded platform-project evidence and report their own platform metadata.
React Native and Expo are separate technology-gated packs: an Expo project can run both, while a
bare React Native project never implies that Expo configuration rules ran.
The Python AI/API pack requires bounded Python/package/framework evidence. It reports unsupported
syntax, source bounds, and deliberately excluded corpora as explicit coverage notes instead of
inferring that omitted source is safe.
The Go, Java, and C# AI packs require their language plus the exact official OpenAI SDK dependency.
The PHP pack requires PHP plus exact openai-php/client or openai-php/laravel Composer evidence;
those packages are community-maintained, not official OpenAI SDKs. A generic openai framework tag
alone cannot activate it.
The Rust pack requires Rust plus exact async-openai Cargo dependency evidence; that crate is
community-maintained, not an official OpenAI SDK. The Ruby pack requires Ruby plus exact official
openai production Gemfile or runtime gemspec evidence; lockfiles remain Ruby-language evidence
because they do not preserve dependency groups. A generic openai framework tag alone
cannot activate Go, Java, C#, PHP, Rust, Ruby, or Python analyzers.
dependency_coverage separately reports whether the native Pub matcher ran, which lockfiles and
eligible packages it analyzed, what it deliberately skipped, and the bundled snapshot version.
Honest claims (please read)
- "No egress" is precise: zero egress at scan time. Engine binaries, the
Trivy DB, and the OSV databases are fetched only by explicit setup/repair commands after your
approval, with SHA256 verification (OSV databases: TLS plus a recorded SHA-256, since OSV
publishes no signature). Normal CodeInspectus installation does not install the optional C2PA peer;
users who explicitly install that upstream package allow its lifecycle download. Nothing is
downloaded during a scan. The scanner functions with the network unplugged. There is no
telemetry, ever.
- Supply-chain pinning is mandatory. Trivy was supply-chain-compromised twice
in early 2026; every engine binary is SHA-pinned in
engines.lock.json and its
hash is verified before execution. CodeInspectus refuses to run an unpinned or
mismatched binary.
- Secret values are redacted in all output — type + location + a redacted
preview only.
- osv-scanner coverage is only as complete as the OSV databases you installed. It matches the
package versions that lockfiles and manifests record, offline, with no reachability or call
analysis. If a repository uses an ecosystem whose OSV database is not installed, the scan reports
that ecosystem as
unavailable with a setup warning; it never reports it as clean. A
repository's own osv-scanner.toml cannot suppress results, because CodeInspectus passes a
managed config. A MAL- (malicious package) finding is reported as critical (CWE-506) with
advice to rotate credentials the package could have reached. Where osv-scanner, Trivy, or the
native Pub matcher report the same advisory for the same package, you see one finding that
lists every engine; the same advisory on two different packages stays two findings.
- Compliance = code-level control coverage, never certification. CodeInspectus
reports "X of N code-visible controls have findings", with the code-visible
subset as the explicit denominator, plus a standing disclaimer. It never emits
"you are X% compliant" or "you pass [framework]". The severity-weighted posture
score is a separate view and is not a percent-compliant figure. Essential
Eight especially: only ~1 of 8 mitigations (Patch Applications) is
code-evidenced — this is not an Essential Eight assessment.
- Prompt-injection detection is heuristic and immature — those findings are
worded "potential …" and marked medium confidence.
- Flutter/Dart native coverage is six narrow, first-party structural checks:
ci-flutter-tls-verification-disabled, ci-flutter-sensitive-shared-preferences,
ci-flutter-webview-untrusted-content, ci-flutter-sensitive-log,
ci-flutter-supabase-privileged-key-client, and ci-flutter-cleartext-network.
They inspect Dart tokens and local source structure without type resolution or whole-program
dataflow. Project-root scans exclude generated files and test/example corpora unless those paths
are scanned directly. Unreadable Dart files, files over 2 MiB, and source beyond the
10,000-file/64 MiB project bounds are skipped and named in pack_coverage. This is repository
evidence, not runtime mobile testing or complete Flutter coverage. Native Pub vulnerability/SBOM
analysis is a separate vuln-class engine, so it can run for Flutter and plain Dart projects
without implying that the Flutter source pack applied. Android/iOS configuration is handled by
separate native platform packs; existing Trivy behavior is unchanged.
The shipped Flutter TP/FP/fixed corpus locks exactly one
expected finding per rule in the vulnerable project and zero findings in both the near-miss and
remediated projects. E23/E24 exercise that corpus through the built MCP stdio server, including
pack execution accounting and redaction of the planted synthetic sentinel.
- Android/iOS native coverage is eight narrow, first-party repository-configuration checks.
Android flags an explicitly debuggable release, effective production cleartext opt-in,
production trust of user-added CAs, and an exported AndroidX FileProvider. iOS flags global ATS
arbitrary loads, insecure production-domain exceptions, weak production-domain TLS policy, and
disabled default data protection. The packs parse bounded, literal XML/Xcode repository evidence;
they never run Gradle, Xcode, or target code, and parsed configuration is never executed. Dynamic
build settings,
arbitrary Android product flavors, full manifest merging, provisioning profiles, runtime behavior,
and complete mobile-platform security remain out of scope. Skipped or unsupported configuration is
named in
pack_coverage, not inferred as secure or vulnerable. The shipped
Android/iOS TP/FP/fixed corpus
and E25/E26 lock exact findings, zero-finding near-miss/remediated states, provenance, redaction,
execution accounting, and bidirectional same-path rescan behavior.
- React Native/Expo native coverage is six narrow, first-party structural checks. The React
Native pack flags sensitive credential writes to proven AsyncStorage receivers, untrusted route/
deep-link content entering an imported JavaScript-enabled WebView, explicit mixed-content opt-in,
and universal-origin access from a file-backed WebView. The separate Expo pack flags sensitive
server environment values placed in public app config and unsigned updates fetched over cleartext
production URLs. Both use bounded read-only parsing and never import, execute, or evaluate target
code/configuration. Dynamic values, spreads, unresolved guards, unreadable/oversized input, and
bounded-out source become named coverage limitations rather than inferred findings. Framework
evidence is required; ordinary JavaScript/TypeScript or native Android/iOS skeletons do not
activate these packs. This is intrafile/static repository evidence, not complete dataflow,
deployment proof, or runtime mobile testing. The shipped
React Native/Expo TP/FP/fixed corpus and E30/E31 lock exact findings,
precision, redaction, provenance, execution accounting, and same-path resolution/reintroduction.
- Python AI/API native coverage is ten narrow first-party structural checks. The pack flags
hardcoded framework signing secrets, credentialed all-origin CORS, request-controlled file
responses and redirects, request-controlled template source, and unsanitized OpenAI/Anthropic
output returned as HTML, explicit LangChain FAISS pickle-deserialization opt-in, and request-controlled
complete URLs fetched by a proven LangChain WebBaseLoader, plus medium-confidence potential
prompt-injection sinks where request input reaches proven OpenAI/Anthropic privileged instructions
or shares the LLM call with configured tool access, and model tool arguments reaching proven
Python shell-execution APIs without a visible checked guard. It uses a bounded Lezer syntax gate plus source-ordered intrafile
analysis; it never imports or executes target Python. There is no type checker, module graph,
interprocedural flow, or path-sensitive branch merge. Lezer-validated format strings are retained
as opaque dynamic values, so their replacement expressions are not inspected; leading-tab indentation
still fails closed with a named coverage note. Generated, migration, dependency, build, test,
fixture, demo, sample, and example trees are excluded from project-root scans. Unsupported,
malformed, symlinked, unreadable, oversized, or bounded-out source is reported, not inferred as
secure. The shipped Python AI/API TP/FP/fixed corpus and E32/E33 lock exact
findings, precision, redaction, provenance, execution accounting, and same-path
resolution/reintroduction.
- Go AI native coverage is one narrow, medium-confidence structural check.
ci-go-llm-tool-argument-command-execution requires the exact official OpenAI Go SDK Chat
Completions tool-call argument shape and import-proven os/exec invocation of a recognized shell
with its command flag. It supports direct aliases, encoding/json.Unmarshal, one local JSON
parser, and one local command wrapper. Checked rejection/approval or allowlist guards and
validated replacement values suppress findings. It does not cover general Go SAST, other model
SDKs, cross-module dispatch, runtime sandboxing, or complete agent safety. The shipped
Go TP/FP/fixed corpus and E37/E38 lock exact findings, zero-finding safe and
fixed states, provenance, pack dispatch, and same-path resolution/reintroduction.
- Java and C# AI native coverage is one narrow, medium-confidence structural check per ecosystem.
Each requires the exact official OpenAI SDK dependency and tool-call argument shape before model
data can reach a recognized, actually-started shell process. Direct aliases, one local parser,
and one local command wrapper are supported; checked rejection/approval or allowlist guards and
validated replacement values suppress findings. These packs do not provide general Java or C#
SAST, cross-module dispatch, runtime sandbox proof, or complete agent review. The shipped
Java and C# TP/FP/fixed corpora and E39-E42 lock exact findings, safe/fixed
silence, provenance, language-gated dispatch, and same-path resolution/reintroduction.
- PHP AI native coverage is one narrow, medium-confidence structural check.
ci-php-llm-tool-argument-command-execution requires exact community-maintained
openai-php/client or openai-php/laravel Composer evidence and model tool-call
function->arguments reaching exec, system, shell_exec, or passthru. It supports direct
aliases, associative json_decode, one local parser, one local command wrapper, and one exact
mapped variadic method dispatch. Checked approval/full-command allowlists and validated
replacement values suppress findings; first-token executable checks do not neutralize shell
metacharacters and do not suppress them. It does not provide general PHP SAST, cross-file flow,
runtime sandbox proof, or complete agent review. The shipped PHP TP/FP/fixed corpus
and E43/E44 lock exact findings, safe/fixed silence, provenance, language-gated dispatch, and
same-path resolution/reintroduction.
- Rust AI native coverage is one narrow, medium-confidence structural check.
ci-rust-llm-tool-argument-command-execution requires exact community-maintained
async-openai Cargo evidence and recognized model tool arguments reaching an import-proven
standard/Tokio process shell or literal Bollard Docker exec shell vector. It supports direct
aliases, serde_json extraction, one recognized generate_function_call result, and one local
command wrapper. Checked approval/allowlist rejection and validated replacement values suppress
findings. It does not provide general Rust SAST, rustc/type/Cargo-graph resolution, cross-crate
flow, runtime container/sandbox proof, or complete agent review. The shipped
Rust TP/FP/fixed corpus and E45/E46 lock exact findings, safe/fixed silence,
provenance, language-gated dispatch, and same-path resolution/reintroduction. async-openai is
community maintained and is not represented as an official OpenAI SDK.
- Ruby AI native coverage is one narrow, medium-confidence structural check.
ci-ruby-llm-tool-argument-command-execution requires exact official production openai Gemfile
or runtime gemspec evidence and
recognizes Chat tool-call function.arguments or explicitly typed Responses function-tool
arguments reaching system, exec, IO.popen, or import-proven Open3 shell execution. It
supports direct aliases, JSON.parse command extraction, one local parser, and one local command
wrapper. Checked approval/full-command allowlists and validated replacements stay silent. It
does not provide general Ruby SAST, Bundler/type resolution, cross-file flow, backtick/percent-x/
spawn coverage, runtime sandbox proof, or complete agent review. The shipped
Ruby TP/FP/fixed corpus and E47/E48 lock exact findings, safe/fixed silence,
provenance, language-gated dispatch, and same-path resolution/reintroduction.
- Firebase native coverage is three narrow, high-confidence configuration checks.
ci-firebase-firestore-public-write, ci-firebase-storage-public-write, and
ci-firebase-realtime-database-public-write flag only checked-in literal write grants with no
condition or a condition exactly equal to true (Realtime Database boolean/string true).
Public reads stay silent because they are often intentional. The bounded parser masks Rules
comments/strings, requires exact Firestore/Storage service declarations, requires strict JSON
for Realtime Database, excludes non-production/dependency/generated trees, and never runs
Firebase tooling or target code. It does not evaluate helper functions, deployed policy, IAM,
App Check, or runtime access. The shipped Firebase TP/FP/fixed corpus and
E49/E50 lock exact findings, safe/fixed silence, provenance, pack dispatch, and same-path
resolution/reintroduction.
- GitHub Actions native coverage is two narrow workflow checks.
ci-github-actions-untrusted-expression-command flags direct documented attacker-controlled
github expressions embedded in run; using an intermediate env value or action with input
stays silent. ci-github-actions-pwn-request requires the complete high-risk chain: exact
pull_request_target, checkout of the pull request's untrusted ref into the default workspace,
and subsequent execution of checked-out code or a local action. Checkout v7 is treated as
protected unless allow-unsafe-pr-checkout is explicitly enabled. The bounded YAML 1.2 parser
reads only direct .github/workflows/*.yml/.yaml files and never executes workflows or target
code. It does not provide general workflow taint analysis, custom-action analysis, artifact-flow
analysis, permission-policy proof, or runner/runtime verification. The shipped
GitHub Actions TP/FP/fixed corpus and E51/E52 lock exact findings,
safe/fixed silence, provenance, dispatch, and same-path resolution/reintroduction.
- Client-side authorization that trusts
user_metadata is flagged (ci-ai-client-metadata-authz).
CodeInspectus detects an authorization decision that reads client-writable Supabase
user_metadata — e.g. if (user.user_metadata.role === 'admin') — at high severity,
medium confidence (CWE-639). user_metadata is editable by the signed-in user themselves
(Supabase's /auth/v1/user endpoint), so anyone can self-assign role: 'admin'; gate
privileged logic on the server-controlled app_metadata.role instead. Detection is intrafile
(inline + split-variable/destructured); it does not yet trace cross-file or whole-object-alias
flows (planned) — see the good-first-issue.
It also catches the related footgun: a Supabase service_role JWT or modern sb_secret_
key value in client-reachable code (critical), and a privileged key behind a
client-exposed env prefix such as NEXT_PUBLIC_… (high). Exact-format
sb_publishable_ keys remain silent because they are public by design. Each secret class is
bounded to 1,024 remediation locations per file; repeated values on one minified line collapse,
separate source lines remain visible, and reaching the bound emits an explicit coverage note.
- Unsanitized model or user output rendered as raw HTML is flagged (
ci-ai-llm-output-dangerous-html).
CodeInspectus detects untrusted request input or LLM/model output flowing into
dangerouslySetInnerHTML without sanitization — a direct XSS sink (CWE-79/116; OWASP LLM05 on
the model-output path), high severity, medium confidence; wrapping the value in
DOMPurify.sanitize(...) silences it. It follows one local function-component hop when a
destructured prop is passed directly to __html; sanitizing at the JSX call site stays silent.
It does not trace cross-file or arrow-component props, database rows, template data,
object-spread sinks, or custom sanitizer wrappers.
- Model output passed to dynamic execution is flagged (
ci-ai-llm-output-dynamic-execution).
CodeInspectus follows direct and split-variable intrafile flows from recognized OpenAI,
Anthropic, Google GenAI, Vercel AI SDK, Cohere, Groq, and Mistral call/output shapes into global
eval/Function, import-proven Node child_process.exec/execSync, or import-proven Execa
command-string APIs. The rule is high severity and medium confidence (CWE-94/78/1426;
OWASP LLM05). Constants, fixed allowlisted dispatch, execFile/spawn argument arrays,
shadowed globals, and explicitly validated replacement values stay silent. Cross-file flows,
custom model wrappers, stream accumulation, indirect sink aliases, and runtime sandbox or
approval state are not resolved.
- Conventional Next.js admin API routes need authentication and authorization
(
ci-ai-nextjs-admin-route-no-authz). Pages Router handlers under pages/api/admin and App
Router handlers under app/api/admin/**/route.* are flagged when either boundary is not visible
in the file (high, medium confidence; CWE-862/863/306; OWASP A01 and API5). Recognized
server-session/token checks plus role/permission decisions stay silent; Supabase client-writable
user_metadata is deliberately not accepted as authorization. Non-admin/public routes stay
silent. The bounded detector follows exact direct, one-local-helper-hop evidence; unsupported
cross-file middleware, custom guard semantics, and dynamic dispatch remain explicit unknowns.
- Import-proven Express admin routes and explicitly anonymous Supabase Edge Functions are checked.
Express analysis requires a literal admin route and direct handler evidence, respects supported
middleware/mount ordering, and reports unresolved custom middleware as coverage metadata. Edge
analysis treats default or explicit
verify_jwt = true as platform authentication; only explicit
anonymous deployment requires visible request authentication, and service-role/admin operations
additionally require visible server authorization. Cross-module custom wrappers remain unknown.
- Server/API-boundary checks are narrow and code-visible. Four JavaScript/TypeScript
analyzers flag client-visible raw/internal error details (
CWE-209), explicit credential
fields in response objects (CWE-201), whole request objects passed directly to common
Prisma/Supabase/Mongoose writes without visible validation or allow-listing (CWE-915),
and explicit credentials/headers/cookies or auth/payment request bodies sent to logs
(CWE-532). They use intrafile dataflow and prefer silence when validation, a public-error
mapper, or an explicit field projection is visible. Build output and minified vendor files are
outside these source checks. They do not claim generic response minimization, complete
business-authorization review, or runtime/gateway verification.
- Runtime security controls use three evidence states, never absence-as-vulnerability.
Supported header/CSP/cookie/CAPTCHA controls report
verified_in_repository,
insecure_configuration_found, or not_verifiable_from_repository. Only an explicit
insecure repository configuration becomes a finding; missing headers, dashboard-only
CAPTCHA, dynamic/conflicting layers, and hosted/gateway configuration remain metadata with
no posture penalty. “Verified” means only that recognized source configuration passed the
rule’s narrow literal check; it is not runtime or complete policy proof. Current findings
cover security headers explicitly disabled or
neutralized, production CSP with bare wildcard or 'unsafe-eval' script sources,
an effective literal Referrer-Policy: unsafe-url, unrestricted camera/microphone/geolocation
delegation in a literal Permissions-Policy,
auth/session cookies with explicit insecure attributes, and checked-in Supabase CAPTCHA
enablement paired with a recognized signup, password/OTP/SSO/Web3 signin, or password-reset
call missing captchaToken. The CAPTCHA finding
describes an integration failure that Supabase should reject—not a bot-protection bypass.
CodeInspectus still does not prove deployed headers, gateway rate limits, DNS mail posture,
complete CSP quality, runtime overrides, or behavioral authentication. SPF/DMARC absence is not
emitted as a repository finding because authoritative state is live DNS, and DMARC p=none is a
valid monitoring mode; verify mail domains explicitly at deployment time.
Language support
Plainly, what runs on what. The commodity engines are broad; the CodeInspectus
native checks are predominantly JavaScript/TypeScript, plus targeted Flutter/Dart,
Android/iOS configuration, React Native, Expo, Python AI/API, and one-rule Go, Java, C#, PHP, Rust,
and Ruby AI packs, plus Firebase Security Rules and GitHub Actions workflow configuration packs. A Python
repository gets native coverage only for the ten documented framework/source shapes; a Go/OpenAI,
Java/OpenAI, C#/OpenAI, PHP/openai-php, Rust/async-openai, or Ruby/OpenAI repository gets only its one documented
tool-execution rule. Other unsupported native-pack ecosystems still receive the selected
commodity-engine coverage but no native pack applies. Plain Dart without Flutter also does not activate the Flutter source pack
(the separate native Pub SCA/SBOM engine can still run). This is stated so you don't infer broader
coverage than the executed pack reports.
Compliance frameworks (code-visible subset)
NIST CSF 2.0 · ISO/IEC 27001:2022 · SOC 2 · CIS Controls v8.1 · Essential Eight
(Patch Applications only) · OWASP Top 10 (2021) · OWASP LLM Top 10 (2025).
MITRE ATT&CK techniques are shown as related-adversary context only, never as a
coverage score.
Relevant findings can also carry OWASP API Security Top 10 (2023) category tags.
Those tags describe the detected failure pattern; they are not an OWASP API review,
coverage score, compliance claim, or certification.
Compliance mappings are AI-drafted, reviewed by a cybersecurity practitioner
(Synvoya) — code-level coverage only, not an audit or certification. Community review
welcome. The CWE→control mappings are self-audited with per-mapping confidence and an
open community-verification process — see
docs/COMPLIANCE-RATIONALE.md and
CONTRIBUTING.md. Essential Eight is not a coverage view: only
Patch Applications is code-evidenced (~1 of 8) — this is not an Essential Eight assessment.
How it works
Example reports
Trademark
"CodeInspectus" is the name of this free, open-source project (npm codeinspectus,
codeinspectus.com). "Code Inspect" is a descriptive phrase in a crowded namespace;
registry availability is not trademark clearance, and the name is not claimed as a
trademark.
Development
How this repository is generated (an auditable, allow-list seed) and built end-to-end:
docs/BUILD.md.
Contributing
CodeInspectus is a solo, free, open-source project, built and maintained by
one cybersecurity practitioner under the Synvoya name. There is no company
behind it and nothing to sell — which is exactly why outside eyes matter.
Independent review is genuinely wanted, not a courtesy line. If you work in
security, your scrutiny is the contribution.
Two areas where review helps most:
- Compliance CWE→control mappings. These are AI-drafted, then policy-reviewed
by the maintainer — they are NOT independently verified. Every mapping is
tracked through three explicit states: AI-drafted → maintainer-policy-reviewed →
community-verified. Today almost everything sits in the first two; the
community-verified count is 0 of 96, and that is reported honestly rather than hidden.
Moving a mapping to community-verified takes evidence (a quote from the control's
primary source + your basis) — the bar and process are in
CONTRIBUTING.md; the per-mapping rationale and confidence live
in docs/COMPLIANCE-RATIONALE.md.
- Detection rules (
detection-db/**, src/ai-checks/**, src/packs/**). New rules, precision
fixes, and false-positive reports are all welcome. The merge bar is precision:
a fixture proving the true positive, and a near-miss fixture proving the rule does
not over-fire. Details in CONTRIBUTING.md.
What CodeInspectus claims — and what it deliberately does not — is written down so
you can check it before trusting a number: the standing compliance disclaimer (in the
Compliance frameworks section above and in
docs/COMPLIANCE-RATIONALE.md) and the three-state
honesty metric. If something reads as over-claiming, that is a bug — please open an issue.
Workflow: fork → branch → PR; the maintainer reviews and merges (external
contributors don't push directly). — Synvoya (the maintainer, a cybersecurity
practitioner)
Good first contributions
Browse all good first issues.
Changelog
Per-version release notes live in CHANGELOG.md.
Licenses
CodeInspectus is licensed under Apache-2.0. The separately downloaded engines retain their own
licenses: Opengrep (LGPL-2.1), Gitleaks (MIT), Trivy (Apache-2.0), and osv-scanner (Apache-2.0).
Engine binaries are not included in the npm package. See
THIRD-PARTY-NOTICES.md for versions, copyright notices, upstream source,
and license links.
The OSV databases osv-scanner reads are downloaded after your approval from OSV's bucket
(osv-vulnerabilities.storage.googleapis.com) and are not re-hosted by CodeInspectus. Each record
keeps its source's license: GitHub Advisory Database, PyPA, OSS-Fuzz, and Go Vulnerability
Database records are CC BY 4.0, OpenSSF Malicious Packages is Apache-2.0, Drupal is MIT, and
RustSec is CC0 1.0. Attribution and the full table are in
THIRD-PARTY-NOTICES.md; this is attribution, not a legal review.
The one exception is the transformed Pub advisory snapshot that ships with CodeInspectus for the
native Pub matcher. It is derived from OSV.dev records sourced from the GitHub Advisory Database
and remains CC BY 4.0; attribution and transformation details ship beside the snapshot in
detection-db/osv-pub/LICENSE-PROVENANCE.md.