22// SPDX-License-Identifier: Apache-2.0
33
44import { access , readFile } from 'node:fs/promises' ;
5+ import { isIP } from 'node:net' ;
56import path from 'node:path' ;
67import { fileURLToPath } from 'node:url' ;
78import { parseArgs } from 'node:util' ;
@@ -19,19 +20,37 @@ const internalPattern = /(?:alibaba-inc\.com|alibabacloud\.com\.cn|localhost|127
1920const secretPattern = / (?: - - - - - B E G I N (?: R S A | E C | O P E N S S H ) ? P R I V A T E K E Y - - - - - | \b A K I A [ 0 - 9 A - Z ] { 16 } \b | \b g h [ p o u s r ] _ [ A - Z a - z 0 - 9 ] { 20 , } \b | \b s k - [ A - Z a - z 0 - 9 _ - ] { 20 , } \b ) / ;
2021let mermaidPromise ;
2122
23+ function privateIpv4 ( octets ) {
24+ const [ first , second ] = octets ;
25+ return first === 0 || first === 10 || first === 127 || ( first === 100 && second >= 64 && second <= 127 )
26+ || ( first === 169 && second === 254 ) || ( first === 172 && second >= 16 && second <= 31 ) || ( first === 192 && second === 168 ) ;
27+ }
28+
29+ function ipv6Words ( value ) {
30+ if ( isIP ( value ) !== 6 ) return null ;
31+ const [ leftSource , rightSource = '' ] = value . split ( '::' ) ;
32+ const parse = ( source ) => source ? source . split ( ':' ) . filter ( Boolean ) . map ( ( part ) => Number . parseInt ( part , 16 ) ) : [ ] ;
33+ const left = parse ( leftSource ) ;
34+ const right = parse ( rightSource ) ;
35+ const omitted = 8 - left . length - right . length ;
36+ if ( ( value . includes ( '::' ) && omitted < 1 ) || ( ! value . includes ( '::' ) && omitted !== 0 ) ) return null ;
37+ return [ ...left , ...Array ( omitted ) . fill ( 0 ) , ...right ] ;
38+ }
39+
2240function isPrivateHostname ( value ) {
2341 const hostname = value . toLowerCase ( ) . replace ( / ^ \[ | \] $ / g, '' ) . replace ( / \. $ / , '' ) ;
2442 if ( hostname === 'localhost' || hostname . endsWith ( '.localhost' ) || hostname . endsWith ( '.local' ) || hostname . endsWith ( '.internal' ) ) return true ;
25- if ( hostname . includes ( ':' ) ) {
26- if ( hostname === '::' || hostname === '::1' || hostname . startsWith ( 'fc' ) || hostname . startsWith ( 'fd' ) || / ^ f e [ 8 9 a b ] / . test ( hostname ) ) return true ;
27- if ( hostname . startsWith ( '::ffff:' ) ) return isPrivateHostname ( hostname . slice ( '::ffff:' . length ) ) ;
28- return false ;
43+ if ( isIP ( hostname ) === 4 ) return privateIpv4 ( hostname . split ( '.' ) . map ( Number ) ) ;
44+ const words = ipv6Words ( hostname ) ;
45+ if ( ! words ) return false ;
46+ if ( ( words [ 0 ] & 0xfe00 ) === 0xfc00 || ( words [ 0 ] & 0xffc0 ) === 0xfe80 ) return true ;
47+ const compatiblePrefix = words . slice ( 0 , 6 ) . every ( ( word ) => word === 0 ) ;
48+ const mappedPrefix = words . slice ( 0 , 5 ) . every ( ( word ) => word === 0 ) && words [ 5 ] === 0xffff ;
49+ if ( compatiblePrefix || mappedPrefix ) {
50+ const octets = [ words [ 6 ] >> 8 , words [ 6 ] & 0xff , words [ 7 ] >> 8 , words [ 7 ] & 0xff ] ;
51+ return privateIpv4 ( octets ) ;
2952 }
30- const octets = hostname . split ( '.' ) . map ( Number ) ;
31- if ( octets . length !== 4 || octets . some ( ( octet ) => ! Number . isInteger ( octet ) || octet < 0 || octet > 255 ) ) return false ;
32- const [ first , second ] = octets ;
33- return first === 0 || first === 10 || first === 127 || ( first === 100 && second >= 64 && second <= 127 )
34- || ( first === 169 && second === 254 ) || ( first === 172 && second >= 16 && second <= 31 ) || ( first === 192 && second === 168 ) ;
53+ return false ;
3554}
3655
3756async function parseMermaid ( diagram ) {
0 commit comments