mirror of
https://github.com/samiyev/puaros.git
synced 2025-12-28 07:16:53 +05:00
194 lines
5.8 KiB
TypeScript
194 lines
5.8 KiB
TypeScript
import { VALUE_PATTERN_TYPES } from "../../shared/constants/ast-node-types"
|
|
|
|
/**
|
|
* Pattern matcher for detecting specific value types
|
|
*
|
|
* Provides pattern matching for emails, IPs, paths, dates, UUIDs, versions, and other common hardcoded values
|
|
*/
|
|
export class ValuePatternMatcher {
|
|
private static readonly EMAIL_PATTERN = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
|
|
private static readonly IP_V4_PATTERN = /^(\d{1,3}\.){3}\d{1,3}$/
|
|
private static readonly IP_V6_PATTERN =
|
|
/^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::([0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$/
|
|
private static readonly DATE_ISO_PATTERN = /^\d{4}-\d{2}-\d{2}$/
|
|
private static readonly URL_PATTERN = /^https?:\/\/|^mongodb:\/\/|^postgresql:\/\//
|
|
private static readonly UNIX_PATH_PATTERN = /^\/[a-zA-Z0-9/_-]+/
|
|
private static readonly WINDOWS_PATH_PATTERN = /^[a-zA-Z]:\\[a-zA-Z0-9\\/_-]+/
|
|
private static readonly API_KEY_PATTERN = /^(sk_|pk_|api_|key_)[a-zA-Z0-9_-]{20,}$/
|
|
private static readonly UUID_PATTERN =
|
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
private static readonly SEMVER_PATTERN = /^\d+\.\d+\.\d+(-[\w.-]+)?(\+[\w.-]+)?$/
|
|
private static readonly HEX_COLOR_PATTERN = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/
|
|
private static readonly MAC_ADDRESS_PATTERN = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/
|
|
private static readonly BASE64_PATTERN =
|
|
/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/
|
|
private static readonly JWT_PATTERN = /^eyJ[A-Za-z0-9-_]+\.eyJ[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$/
|
|
|
|
/**
|
|
* Checks if value is an email address
|
|
*/
|
|
public isEmail(value: string): boolean {
|
|
return ValuePatternMatcher.EMAIL_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is an IP address (v4 or v6)
|
|
*/
|
|
public isIpAddress(value: string): boolean {
|
|
return (
|
|
ValuePatternMatcher.IP_V4_PATTERN.test(value) ||
|
|
ValuePatternMatcher.IP_V6_PATTERN.test(value)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is a date in ISO format
|
|
*/
|
|
public isDate(value: string): boolean {
|
|
return ValuePatternMatcher.DATE_ISO_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is a URL
|
|
*/
|
|
public isUrl(value: string): boolean {
|
|
return ValuePatternMatcher.URL_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is a file path (Unix or Windows)
|
|
*/
|
|
public isFilePath(value: string): boolean {
|
|
return (
|
|
ValuePatternMatcher.UNIX_PATH_PATTERN.test(value) ||
|
|
ValuePatternMatcher.WINDOWS_PATH_PATTERN.test(value)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Checks if value looks like an API key
|
|
*/
|
|
public isApiKey(value: string): boolean {
|
|
return ValuePatternMatcher.API_KEY_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is a UUID
|
|
*/
|
|
public isUuid(value: string): boolean {
|
|
return ValuePatternMatcher.UUID_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is a semantic version
|
|
*/
|
|
public isSemver(value: string): boolean {
|
|
return ValuePatternMatcher.SEMVER_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is a hex color
|
|
*/
|
|
public isHexColor(value: string): boolean {
|
|
return ValuePatternMatcher.HEX_COLOR_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is a MAC address
|
|
*/
|
|
public isMacAddress(value: string): boolean {
|
|
return ValuePatternMatcher.MAC_ADDRESS_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is Base64 encoded (min length 20 to avoid false positives)
|
|
*/
|
|
public isBase64(value: string): boolean {
|
|
return value.length >= 20 && ValuePatternMatcher.BASE64_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Checks if value is a JWT token
|
|
*/
|
|
public isJwt(value: string): boolean {
|
|
return ValuePatternMatcher.JWT_PATTERN.test(value)
|
|
}
|
|
|
|
/**
|
|
* Detects the type of value
|
|
*/
|
|
public detectType(
|
|
value: string,
|
|
):
|
|
| "email"
|
|
| "url"
|
|
| "ip_address"
|
|
| "file_path"
|
|
| "date"
|
|
| "api_key"
|
|
| "uuid"
|
|
| "version"
|
|
| "color"
|
|
| "mac_address"
|
|
| "base64"
|
|
| null {
|
|
if (this.isEmail(value)) {
|
|
return VALUE_PATTERN_TYPES.EMAIL
|
|
}
|
|
if (this.isJwt(value)) {
|
|
return VALUE_PATTERN_TYPES.API_KEY
|
|
}
|
|
if (this.isApiKey(value)) {
|
|
return VALUE_PATTERN_TYPES.API_KEY
|
|
}
|
|
if (this.isUrl(value)) {
|
|
return VALUE_PATTERN_TYPES.URL
|
|
}
|
|
if (this.isIpAddress(value)) {
|
|
return VALUE_PATTERN_TYPES.IP_ADDRESS
|
|
}
|
|
if (this.isFilePath(value)) {
|
|
return VALUE_PATTERN_TYPES.FILE_PATH
|
|
}
|
|
if (this.isDate(value)) {
|
|
return VALUE_PATTERN_TYPES.DATE
|
|
}
|
|
if (this.isUuid(value)) {
|
|
return VALUE_PATTERN_TYPES.UUID
|
|
}
|
|
if (this.isSemver(value)) {
|
|
return VALUE_PATTERN_TYPES.VERSION
|
|
}
|
|
if (this.isHexColor(value)) {
|
|
return "color"
|
|
}
|
|
if (this.isMacAddress(value)) {
|
|
return VALUE_PATTERN_TYPES.MAC_ADDRESS
|
|
}
|
|
if (this.isBase64(value)) {
|
|
return VALUE_PATTERN_TYPES.BASE64
|
|
}
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Checks if value should be detected as hardcoded
|
|
*/
|
|
public shouldDetect(value: string): boolean {
|
|
return (
|
|
this.isEmail(value) ||
|
|
this.isUrl(value) ||
|
|
this.isIpAddress(value) ||
|
|
this.isFilePath(value) ||
|
|
this.isDate(value) ||
|
|
this.isApiKey(value) ||
|
|
this.isUuid(value) ||
|
|
this.isSemver(value) ||
|
|
this.isHexColor(value) ||
|
|
this.isMacAddress(value) ||
|
|
this.isBase64(value) ||
|
|
this.isJwt(value)
|
|
)
|
|
}
|
|
}
|