Overview
This workflow runs weekly to audit your MCP server configurations for security issues. It checks for hardcoded API keys, validates that credentials are pulled from environment variables, verifies key rotation dates, and tests that endpoints are not publicly exposed without authentication. The output is a structured report that feeds into your security review process.
Trigger
Cron schedule (every Monday at 6 AM UTC)
Schedule
Weekly Monday 6 AM
Workflow Steps
Scan MCP config files
Find all MCP server configuration files and parse them for credential references.
Check for hardcoded secrets
Pattern-match config values against known API key formats to detect hardcoded credentials.
Validate environment variable usage
Verify that all credential fields reference environment variables rather than literal values.
Test API key validity
Make a minimal API call with each configured key to verify it is still valid and has appropriate scope.
Check key age
Compare key creation dates against rotation policy to flag stale credentials.
Generate audit report
Compile findings into a structured JSON report with severity levels and remediation steps.
Python Implementation
import requests
import json
import re
import os
from pathlib import Path
from datetime import datetime
API_KEY = os.environ.get("SCAVIO_API_KEY", "")
ROTATION_DAYS = 90
MCP_CONFIG_PATHS = [
Path.home() / ".mcp" / "config.json",
Path(".mcp.json"),
Path("mcp-config.json"),
]
KEY_PATTERNS = [
re.compile(r"sk-[a-zA-Z0-9]{20,}"),
re.compile(r"[a-f0-9]{32,64}"),
re.compile(r"key_[a-zA-Z0-9]{16,}"),
]
def scan_configs() -> list[dict]:
findings = []
for config_path in MCP_CONFIG_PATHS:
if not config_path.exists():
continue
content = config_path.read_text()
config = json.loads(content)
# Check for hardcoded keys
for pattern in KEY_PATTERNS:
matches = pattern.findall(content)
for match in matches:
if not match.startswith("$"):
findings.append({
"file": str(config_path),
"severity": "high",
"issue": "hardcoded_credential",
"value_preview": f"{match[:8]}...",
"remediation": "Move to environment variable",
})
# Check env var references
servers = config.get("mcpServers", config.get("servers", {}))
for name, server_config in servers.items():
env_vars = server_config.get("env", {})
for key, value in env_vars.items():
if not value.startswith("$") and len(value) > 16:
findings.append({
"file": str(config_path),
"severity": "medium",
"issue": "literal_env_value",
"server": name,
"key": key,
"remediation": "Use environment variable reference",
})
return findings
def test_key_validity() -> dict:
if not API_KEY:
return {"status": "missing", "severity": "critical"}
try:
res = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": "test"},
timeout=10,
)
if res.status_code == 200:
return {"status": "valid", "severity": "none"}
elif res.status_code == 401:
return {"status": "expired", "severity": "critical"}
else:
return {"status": "error", "code": res.status_code, "severity": "high"}
except Exception as e:
return {"status": "unreachable", "error": str(e), "severity": "high"}
def run():
report = {
"audit_date": datetime.utcnow().isoformat(),
"config_findings": scan_configs(),
"key_validity": test_key_validity(),
"recommendations": [],
}
high_severity = [f for f in report["config_findings"] if f["severity"] == "high"]
if high_severity:
report["recommendations"].append("Rotate all hardcoded credentials immediately")
if report["key_validity"]["severity"] != "none":
report["recommendations"].append("Fix API key authentication issue")
output = Path(f"mcp_audit_{datetime.utcnow().strftime('%Y-%m-%d')}.json")
output.write_text(json.dumps(report, indent=2))
print(f"Audit complete: {len(report['config_findings'])} findings")
print(f"Key status: {report['key_validity']['status']}")
if __name__ == "__main__":
run()JavaScript Implementation
const API_KEY = process.env.SCAVIO_API_KEY ?? "";
const ROTATION_DAYS = 90;
const KEY_PATTERNS = [
/sk-[a-zA-Z0-9]{20,}/g,
/[a-f0-9]{32,64}/g,
/key_[a-zA-Z0-9]{16,}/g,
];
// Truncated for build safety
Platforms Used
Web search with knowledge graph, PAA, and AI overviews