
Research
TeamPCP Compromises Telnyx Python SDK to Deliver Credential-Stealing Malware
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.
@snytch/nextjs
Advanced tools
Bundle scanning, NEXT_PUBLIC_ exposure detection, and environment drift for Next.js
Bundle scanning, secret detection, and environment exposure analysis for Next.js applications.
With Next.js, an environment variable without the NEXT_PUBLIC_ prefix can still end up in a client bundle if it's imported by a shared module, a utility function, or a component that renders on both server and client. By the time it's in production, it's in every visitor's browser, your build artifacts, your CDN cache, and potentially your git history.
The scale of this problem is larger than most teams realize. According to GitGuardian's 2026 State of Secrets Sprawl Report, codebases leaked 28.6 million secrets in public GitHub repositories in 2025 alone, a 34% year-over-year increase. More concerning: 64% of secrets from 2022 are still exploitable today.
@snytch/nextjs scans your compiled bundle, checks your .env files, and compares your environments to catch these issues before they reach production.
.next/ directory) for snytch scan@snytch/nextjs works best on established Next.js projects that already have a build in place. Run npm run build first to generate the .next directory, then install and scan.
npm install -D @snytch/nextjs
snytch scanScan the compiled Next.js bundle for leaked secrets in client-side JavaScript.
# Basic scan — prints findings to the terminal
snytch scan
# Generate an HTML report and fail the build on any critical finding
snytch scan --report --fail-on critical
# Use a custom .next directory
snytch scan --dir ./apps/web/.next
| Option | Default | Description |
|---|---|---|
--dir | ./.next | Path to the .next directory |
--json | off | Output results as JSON |
--report | off | Generate an HTML report at ./snytch-reports/snytch-report.html |
--fail-on | critical | Exit code threshold: critical, warning, or all |
--ai-provider | anthropic | AI RCA provider: anthropic (requires ANTHROPIC_API_KEY) or openai (requires OPENAI_API_KEY) or none |

snytch checkCheck .env files for NEXT_PUBLIC_ variables that look like secrets. Any variable prefixed with NEXT_PUBLIC_ is embedded into the client bundle at build time and sent to every browser that loads your app. This command flags values that match known secret patterns or look high-entropy enough to be credentials.
# Auto-detect .env files in the current directory
snytch check
# Check specific files
snytch check --env .env.local --env .env.production
# Generate an HTML report
snytch check --env .env.local --report
| Option | Default | Description |
|---|---|---|
--env | auto-detected | Path to a .env file. Repeat for multiple files. |
--json | off | Output results as JSON |
--report | off | Generate an HTML report at ./snytch-reports/snytch-check-report.html |
--fail-on | critical | Exit code threshold: critical, warning, or all |
snytch diffCompare environment variable key presence across two or more .env files. "Drift" means a key exists in one environment but not another. This is how secrets get misconfigured in production: a key is added to .env.local during development and never makes it into .env.production, or a key is removed from one file but not the others.
snytch diff only compares key names, never values. It tells you what is missing or mismatched, not what the values are.
# Compare two environments
snytch diff --env .env.staging --env .env.production
# Compare three environments
snytch diff --env .env.staging --env .env.production --env .env.local
# Generate an HTML report and exit 1 for any drift (not just serverOnly keys)
snytch diff --env .env.staging --env .env.production --report --strict
| Option | Default | Description |
|---|---|---|
--env | required | Path to a .env file. Must be provided at least twice. |
--json | off | Output results as JSON |
--report | off | Generate an HTML report at ./snytch-reports/snytch-diff-report.html |
--strict | off | Exit 1 for any drift, not just serverOnly keys |

snytch mcpStart the snytch MCP server on stdio transport. You don't run this directly. Your editor runs it for you based on the config file you provide. See MCP Server below for setup instructions.
snytch mcp
snytch demoRuns a fully synthetic end-to-end demonstration of all three commands (scan, check, and diff) using fake findings that cover the full range of severity levels and pattern types. Output is identical to a real run: the same formatters, the same exit code (1), and real HTML reports written to disk.
snytch demo
Three report files are generated in your current directory:
| File | Contents |
|---|---|
snytch-reports/snytch-report.html | Bundle scan findings with Findings and AI RCA tabs |
snytch-reports/snytch-check-report.html | NEXT_PUBLIC_ exposure findings |
snytch-reports/snytch-diff-report.html | Environment variable drift across .env files |
Add this to your
.gitignoreto avoid committing the reports directory:snytch-reports/
To see the AI RCA tab populated with real analysis, set an API key before running:
# Anthropic (Claude)
ANTHROPIC_API_KEY=sk-ant-... snytch demo
# OpenAI (GPT-4o)
OPENAI_API_KEY=sk-... snytch demo --ai-provider openai
You will be prompted to delete the generated report files when the demo completes.

.next/static/chunks recursively for JavaScript and CSS files--report is set@snytch/nextjs includes an MCP server so you can run scans directly from inside Cursor, Windsurf, or Claude Desktop without touching a terminal.
Once configured, you can ask your AI assistant things like:
The assistant gets structured results back and can propose fixes inline, in the files where the problem lives. Secret values are never transmitted through the MCP layer - only truncated values are passed to the AI.
| Tool | Description |
|---|---|
snytch_scan | Scan the Next.js bundle for leaked secrets in client-side JS |
snytch_check | Check .env files for dangerous NEXT_PUBLIC_ prefix usage |
snytch_diff | Compare environment variable key presence across .env files |
snytch_scan
// Input
{ "dir": "./.next" } // optional — defaults to <cwd>/.next
// Output
{
"findings": [...], // truncated values only, rca omitted
"summary": { "scannedFiles": 12, "total": 2, "critical": 1, "warning": 1, "durationMs": 80 }
}
snytch_check
// Input
{ "envFiles": [".env.local", ".env.production"] } // optional — auto-detects from cwd
// Output
{
"findings": [...],
"summary": { "scannedFiles": 2, "total": 1, "critical": 1, "warning": 0, "durationMs": 5 }
}
snytch_diff
// Input
{ "envFiles": [".env.staging", ".env.production"] } // required — minimum 2 files
// Output (key names only — values are never read into output)
{
"inSync": ["DATABASE_URL", "REDIS_URL"],
"drift": [{ "key": "API_KEY", "presentIn": [".env.staging"], "missingFrom": [".env.production"] }],
"onlyInOne": [{ "key": "DEV_FLAG", "file": ".env.staging" }]
}
The MCP server runs in the directory where your editor is opened, so it automatically picks up the correct .next directory and .env files for your project. No path configuration needed.
.cursor/mcp.json in your project root.{
"mcpServers": {
"snytch": {
"command": "npx",
"args": ["-y", "@snytch/nextjs", "mcp"]
}
}
}
snytch appears with a green status indicator.~/.codeium/windsurf/mcp_config.json (create it if it doesn't exist).{
"mcpServers": {
"snytch": {
"command": "npx",
"args": ["-y", "@snytch/nextjs", "mcp"]
}
}
}
Open the Claude Desktop config file for your platform (create it if it doesn't exist):
| Platform | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
Add the following:
{
"mcpServers": {
"snytch": {
"command": "npx",
"args": ["-y", "@snytch/nextjs", "mcp"]
}
}
}
snytch_scan, snytch_check, and snytch_diff are listed.Create snytch.config.js in your project root to customize snytch's behavior. The file must use ESM syntax since @snytch/nextjs is an ESM package.
// snytch.config.js
export default {
serverOnly: ['DATABASE_URL', 'STRIPE_SECRET_KEY', 'NEXTAUTH_SECRET'],
failOn: 'critical',
rca: {
maxTokens: 2048,
},
};
| Option | Type | Description |
|---|---|---|
serverOnly | string[] | Variable names that must never be exposed to the client |
failOn | 'critical' | 'warning' | 'all' | Default exit code threshold for all commands |
rca.maxTokens | number | Max tokens for AI RCA responses (default: 2048). Increase if responses are being truncated. |
When serverOnly is set:
snytch check will flag any listed key that appears under NEXT_PUBLIC_snytch diff will exit 1 in non-strict mode if a serverOnly key has driftedsnytch scan will detect literal values of these variables in the bundleRunning snytch in CI catches secrets before they reach production. The scan command exits with code 1 when findings at or above the specified severity are found, so it works as a pipeline gate without any extra configuration.
The bundle must be built before scanning, so add the scan step after your build step.
- name: Build
run: npm run build
- name: Scan bundle for secrets
run: npx @snytch/nextjs scan --fail-on critical
- name: Check NEXT_PUBLIC_ variables
run: npx @snytch/nextjs check --fail-on critical
To also check environment drift across your .env files, add:
- name: Diff env files
run: npx @snytch/nextjs diff --env .env.staging --env .env.production
The
diffstep requires your.envfiles to be present in the CI environment. If they are not checked into the repo, you will need to write them from secrets before this step runs.
MIT
FAQs
Bundle scanning, NEXT_PUBLIC_ exposure detection, and environment drift for Next.js
The npm package @snytch/nextjs receives a total of 2,012 weekly downloads. As such, @snytch/nextjs popularity was classified as popular.
We found that @snytch/nextjs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.

Security News
/Research
Widespread GitHub phishing campaign uses fake Visual Studio Code security alerts in Discussions to trick developers into visiting malicious website.