Code Sentinel — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Code Sentinel (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A comprehensive code quality analysis server for the Model Context Protocol (MCP). CodeSentinel integrates with Claude Code and other MCP-compatible clients to detect security vulnerabilities, deceptive patterns, incomplete code, and highlight good practices.
AI coding assistants can inadvertently introduce subtle issues: hardcoded secrets, empty catch blocks, TODO placeholders left behind, or patterns that hide errors. CodeSentinel acts as a quality gate, analyzing code for 93 distinct patterns across 5 categories before issues reach production.
Key differentiators:
CodeSentinel intentionally uses a pattern-based approach rather than AST parsing. Here's why:
Traditional linters (ESLint, tree-sitter) detect syntax errors and style violations. CodeSentinel detects semantically deceptive patterns - code that is:
// AST sees: valid try-catch block
// CodeSentinel sees: error swallowing that masks failures
try { riskyOperation(); } catch(e) { }
// AST sees: valid function returning boolean
// CodeSentinel sees: fake implementation that always succeeds
function validateUser() { return true; } // TODO: implement
// AST sees: valid fallback expression
// CodeSentinel sees: failure masking - "no data" vs "fetch failed" indistinguishable
const users = response.data || [];
// AST sees: valid return statement
// CodeSentinel sees: silent failure hiding
if (error) { return null; } // error case| Issue Type | AST/Tree-sitter | CodeSentinel |
|---|---|---|
| Syntax errors | Yes | No (not our goal) |
| Missing semicolons | Yes | No |
| Unused variables | Yes | No |
| Empty catch blocks | Partially | Yes |
| Silent error returns | No | Yes |
| Fake success responses | No | Yes |
| TODO/placeholder code | No | Yes |
| Error-masking fallbacks | No | Yes |
| Hardcoded secrets | Limited | Yes |
| Deceptive comments | No | Yes |
AI coding agents produce code that looks correct but contains subtle deceptions:
return true, return [], TODO comments|| [] fallbacks that mask fetch failures@ts-ignore, eslint-disable to hide type errorsThese patterns pass every linter and compile successfully. AST tools see valid structure. Only pattern-based detection catches the semantic intent behind the code.
| Tool | Use For |
|---|---|
| ESLint/TSLint | Style consistency, syntax rules, unused code |
| Tree-sitter | Syntax highlighting, code navigation, refactoring |
| TypeScript | Type safety, compile-time errors |
| CodeSentinel | Agent-generated deceptions, error hiding, incomplete implementations |
CodeSentinel complements these tools - it catches what they structurally cannot.
npm install -g code-sentinel-mcpgit clone https://github.com/salrad22/code-sentinel.git
cd code-sentinel
npm install
npm run buildclaude mcp add code-sentinel -- npx code-sentinel-mcpclaude mcp add code-sentinel -- code-sentinelAdd to your Claude Code MCP configuration file (~/.claude/claude_desktop_config.json):
{
"mcpServers": {
"code-sentinel": {
"command": "npx",
"args": ["code-sentinel-mcp"]
}
}
}CodeSentinel is also available as a remote MCP server on Cloudflare Workers. No local installation required!
claude mcp add-remote code-sentinel https://code-sentinel-mcp.sharara.dev/sseOr use the Streamable HTTP endpoint (recommended for newer clients):
claude mcp add --transport http code-sentinel https://code-sentinel-mcp.sharara.dev/mcp| Endpoint | Protocol | Description |
|---|---|---|
https://code-sentinel-mcp.sharara.dev/mcp | Streamable HTTP | Recommended |
https://code-sentinel-mcp.sharara.dev/sse | Server-Sent Events | Legacy support |
https://code-sentinel-mcp.sharara.dev/ | HTTP GET | Health check / server info |
Deploy your own instance:
cd cloudflare
npm install
npm run dev # Local development at localhost:8787
npm run deploy # Deploy to your Cloudflare accountRequirements:
npm install -g wrangler)wrangler login to authenticateThe server uses Durable Objects for persistent MCP connections. No database required.
analyze_codeFull analysis returning structured JSON with all issues and strengths. Best for programmatic processing.
Parameters:
code (string, required): The source code to analyzefilename (string, required): Filename for language detection (e.g., "app.ts")Returns: JSON object with issues, strengths, and summary statistics.
generate_reportFull analysis with a visual HTML report. Best for human review.
Parameters:
code (string, required): The source code to analyzefilename (string, required): Filename for language detectionReturns: Markdown summary plus complete HTML report.
check_securitySecurity-focused analysis only. Use when you specifically want to audit for vulnerabilities.
Parameters:
code (string, required): The source code to checkfilename (string, required): FilenameReturns: List of security issues or confirmation of none found.
check_deceptive_patternsCheck for code patterns that hide errors or create false confidence.
Parameters:
code (string, required): The source code to checkfilename (string, required): FilenameReturns: List of deceptive patterns found.
check_placeholdersFind TODOs, dummy data, and incomplete implementations.
Parameters:
code (string, required): The source code to checkfilename (string, required): FilenameReturns: List of placeholder code found.
analyze_patternsAnalyze code for architectural, design, and implementation patterns. Detects pattern usage, inconsistencies, and provides actionable suggestions.
Parameters:
code (string, required): The source code to analyzefilename (string, required): Filename for language detectionlevel (string, optional): Pattern level to analyze:architectural: System structure patterns (layering, modules)design: Gang of Four patterns (Singleton, Factory, Observer)code: Implementation idioms (error handling, async patterns)all: All levels (default)query (string, optional): Natural language query to focus analysis (e.g., "how is error handling done?")Returns: LLM-optimized JSON with detected patterns, inconsistencies, suggestions, and ready-to-execute action items.
analyze_design_patternsFocused analysis of Gang of Four (GoF) design patterns. Best for understanding OOP structure.
Parameters:
code (string, required): The source code to analyzefilename (string, required): Filename for language detectionReturns: Detected design patterns with confidence levels, locations, and implementation details.
Ask Claude to analyze code:
Analyze this code for quality issues:
const API_KEY = "sk-abc123456789";
async function fetchData() {
try {
const response = await fetch(url);
return response.json();
} catch (e) {
// TODO: handle error
}
}CodeSentinel will detect:
| ID | Pattern |
|---|---|
| SEC001 | Hardcoded secrets (API keys, tokens, passwords) |
| SEC002 | GitHub tokens |
| SEC003 | OpenAI API keys |
| SEC004 | AWS access keys |
| SEC005-010 | SQL injection patterns |
| SEC011-015 | XSS vulnerabilities |
| SEC016 | Command injection (eval, exec) |
| ID | Pattern | ||||
|---|---|---|---|---|---|
| DEC001-003 | Empty/comment-only catch blocks | ||||
| DEC010-012 | Silent promise rejections | ||||
| DEC020-025 | Error-hiding fallbacks ( | [], | {}, ?? default) | ||
| DEC030+ | Linter suppression, fake success responses |
| ID | Pattern |
|---|---|
| PH001-005 | TODO/FIXME/HACK/XXX/NOTE comments |
| PH010-015 | Lorem ipsum, placeholder text |
| PH020-025 | Test/dummy data ([email protected], password123) |
| PH030+ | console.log debugging, debugger statements |
| ID | Pattern |
|---|---|
| ERR001-005 | Loose equality (==), type coercion issues |
| ERR010-015 | Null reference risks |
| ERR020-025 | Async anti-patterns |
| ERR030+ | parseInt without radix, array mutation in loops |
| ID | Pattern |
|---|---|
| STR001-005 | TypeScript strict typing |
| STR010-015 | Proper error handling patterns |
| STR020-025 | Test coverage indicators |
| STR030+ | Documentation, input validation |
Quality score (0-100) calculated as:
Score = 100 - (critical × 25) - (high × 15) - (medium × 5) - (low × 1) + (strengths × 2)| Severity | Point Deduction |
|---|---|
| Critical | -25 points |
| High | -15 points |
| Medium | -5 points |
| Low | -1 point |
| Strength | +2 points (bonus) |
CodeSentinel detects language from file extensions:
| Extension | Language |
|---|---|
.ts, .tsx | TypeScript |
.js, .jsx | JavaScript |
.py | Python |
.go | Go |
.rs | Rust |
.java | Java |
.kt | Kotlin |
.swift | Swift |
.cs | C# |
.cpp, .c | C/C++ |
.php | PHP |
.vue | Vue |
.svelte | Svelte |
CodeSentinel uses a data-driven pattern system that separates pattern definitions from regex generation. This makes adding new patterns easier and more maintainable.
src/
├── patterns/
│ ├── types.ts # Type definitions for pattern configs
│ ├── builders.ts # Functions that generate regex from configs
│ ├── compiler.ts # Compiles definitions to executable patterns
│ └── definitions/
│ ├── security.ts # Security vulnerability patterns
│ ├── deceptive.ts # Error-hiding patterns
│ ├── placeholders.ts # Incomplete code patterns
│ ├── errors.ts # Code smell patterns
│ └── index.ts # Exports all definitions
├── analyzers/
│ ├── core.ts # Unified analyzer using compiled patterns
│ ├── security.ts # Security analyzer (delegates to core)
│ ├── deceptive.ts # Deceptive analyzer (delegates to core)
│ ├── placeholders.ts # Placeholder analyzer (delegates to core)
│ ├── errors.ts # Error analyzer (delegates to core)
│ └── strengths.ts # Strength analyzer
└── index.ts # MCP server entry pointInstead of writing regex manually, you define what to detect and the system generates the regex:
// Old approach (manual regex)
{
id: 'CS-DEC001',
pattern: /catch\s*\([^)]*\)\s*\{\s*\}/g, // Error-prone
title: 'Empty Catch Block',
// ...
}
// New approach (data-driven)
{
id: 'CS-DEC001',
title: 'Empty Catch Block',
description: 'Silently swallowing errors makes debugging impossible.',
severity: 'high',
category: 'deceptive',
suggestion: 'At minimum, log the error. Better: handle it appropriately.',
match: {
type: 'catch_handler',
behavior: 'empty'
}
}| Match Type | Description | Example Config | ||
|---|---|---|---|---|
empty_block | Empty catch/finally/promise blocks | { type: 'empty_block', constructs: ['catch', '.catch'] } | ||
function_call | Function/method calls | { type: 'function_call', names: ['eval', 'exec'] } | ||
returns_only | Return statements with specific values | { type: 'returns_only', values: ['null', '[]', '{}'] } | ||
contains_text | Text in comments/strings | { type: 'contains_text', terms: ['TODO', 'FIXME'], context: 'comment' } | ||
fallback_value | Fallback patterns | `{ type: 'fallback_value', operators: ['\ | \ | '], values: ['[]'] }` |
catch_handler | Catch block behaviors | { type: 'catch_handler', behavior: 'empty' } | ||
promise_catch | Promise .catch() behaviors | { type: 'promise_catch', behavior: 'returns_silent' } | ||
comment_marker | TODO/FIXME/HACK markers | { type: 'comment_marker', markers: ['TODO', 'FIXME'] } | ||
string_literal | Patterns inside strings | { type: 'string_literal', patterns: ['password', 'secret'] } | ||
secret_pattern | API keys and tokens | { type: 'secret_pattern', kind: 'github' } | ||
url_pattern | URL patterns | { type: 'url_pattern', protocol: 'http', excludeLocalhost: true } | ||
suppression_comment | Linter suppressions | { type: 'suppression_comment', tools: ['ts-ignore', 'eslint-disable'] } | ||
type_cast | Type casts | { type: 'type_cast', targets: ['any'] } | ||
comparison | Comparison operators | { type: 'comparison', operators: ['==', '!='] } | ||
loop_pattern | Loop patterns | { type: 'loop_pattern', kind: 'while_true' } | ||
raw_regex | Escape hatch for complex patterns | { type: 'raw_regex', pattern: 'your-regex', flags: 'gi' } |
src/patterns/definitions/<category>.tsnpm run build{
id: string; // Unique ID: CS-<CAT><NUM> (e.g., CS-SEC001)
title: string; // Short description (displayed in results)
description: string; // Detailed explanation of the issue
severity: Severity; // 'critical' | 'high' | 'medium' | 'low' | 'info'
category: Category; // 'security' | 'deceptive' | 'placeholder' | 'error'
suggestion?: string; // How to fix the issue
match: MatchConfig; // What to detect (see match types above)
verification?: { // Optional: reduce false positives
status: 'needs_verification' | 'confirmed';
assumption?: string;
confirmIf?: string;
falsePositiveIf?: string;
}
}# Install dependencies
npm install
# Build
npm run build
# Watch mode
npm run watch
# Test with MCP inspector
npm run inspectorContributions welcome! Please:
MIT
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.