@@ -2,16 +2,26 @@ import { Finding, RuleId, Severity } from '../types.js';
22import { ParsedMcpConfig } from '../parser.js' ;
33import { Rule } from './index.js' ;
44
5+ /**
6+ * Auth `type` values that explicitly mean "no authentication". A config that
7+ * declares one of these is unauthenticated, even though the `auth` block exists.
8+ */
9+ const DISABLED_AUTH_TYPES = new Set ( [ 'none' , 'disabled' , 'off' , 'false' , 'anonymous' ] ) ;
10+
511export const authRules : Rule [ ] = [
612 {
713 id : RuleId . NO_AUTH ,
814 severity : Severity . CRITICAL ,
915 title : 'No Authentication Configured' ,
1016 check ( config : ParsedMcpConfig ) : Finding [ ] {
11- const hasAuth = config . transport ?. auth &&
12- ( config . transport . auth . apiKey ||
13- config . transport . auth . token ||
14- config . transport . auth . type ) ;
17+ const auth = config . transport ?. auth ;
18+ // A real credential always counts as auth.
19+ const hasCredential = Boolean ( auth ?. apiKey || auth ?. token ) ;
20+ // An auth `type` only counts when it names a real mechanism — values like
21+ // "none" or "disabled" explicitly opt out of authentication.
22+ const type = auth ?. type ?. trim ( ) . toLowerCase ( ) ;
23+ const hasMeaningfulType = Boolean ( type ) && ! DISABLED_AUTH_TYPES . has ( type as string ) ;
24+ const hasAuth = hasCredential || hasMeaningfulType ;
1525
1626 if ( ! hasAuth ) {
1727 return [
@@ -22,6 +32,9 @@ export const authRules: Rule[] = [
2232 description :
2333 'The MCP server transport has no authentication configured. ' +
2434 'Any client can connect and invoke tools without credentials.' ,
35+ evidence : hasMeaningfulType === false && Boolean ( type )
36+ ? `transport.auth.type: "${ auth ?. type } " (authentication explicitly disabled)`
37+ : 'transport.auth: absent' ,
2538 remediation :
2639 'Configure authentication in transport.auth (e.g., apiKey, bearer token, or mTLS).' ,
2740 docsUrl : 'https://hailbytes.com/mcp/docs/rules/NO_AUTH' ,
0 commit comments