Skip to content

πŸ›‘οΈ Container and Kubernetes security scanner with sealed classes and data classes - Kotlin

Notifications You must be signed in to change notification settings

bad-antics/nullsec-kotlinguard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 

Repository files navigation

NullSec KotlinGuard

Container Security Scanner written in Kotlin

Version Language License

Part of the NullSec offensive security toolkit
Discord: discord.gg/killers
Portal: bad-antics.github.io

Overview

KotlinGuard is a container and Kubernetes security scanner that identifies misconfigurations, privilege escalation risks, and exposed secrets. Built with Kotlin's sealed classes, data classes, and extension functions for type-safe, expressive security analysis.

Kotlin Features Showcased

  • Sealed Classes: Exhaustive type hierarchies
  • Data Classes: Immutable value objects
  • Extension Functions: Add methods to existing types
  • Object Declarations: Thread-safe singletons
  • Higher-Order Functions: Functional composition
  • Null Safety: Built-in nullable types
  • String Templates: Expressive string formatting
  • Collection Builders: buildList, buildMap

Security Checks

Category Check Severity MITRE
Privileges Privileged mode CRITICAL T1611
Privileges Dangerous capabilities HIGH T1611
Mounts Docker socket CRITICAL T1611
Mounts Sensitive paths HIGH T1552
Secrets Env credentials MEDIUM T1552.001
User Running as root MEDIUM T1078.003
Filesystem Writable rootfs LOW T1485
K8s Host namespaces HIGH T1557

Installation

# Clone
git clone https://github.com/bad-antics/nullsec-kotlinguard.git
cd nullsec-kotlinguard

# Build with Gradle
./gradlew build

# Or compile directly
kotlinc KotlinGuard.kt -include-runtime -d kotlinguard.jar
java -jar kotlinguard.jar

Usage

# Run demo mode
java -jar kotlinguard.jar

# Scan Docker containers
java -jar kotlinguard.jar --docker

# Scan Kubernetes resources
java -jar kotlinguard.jar --k8s --namespace default

# JSON output
java -jar kotlinguard.jar --json

Options

USAGE:
    kotlinguard [OPTIONS]

OPTIONS:
    --docker         Scan Docker containers
    --k8s            Scan Kubernetes resources
    -n, --namespace  Kubernetes namespace
    --json           JSON output format
    -v, --verbose    Verbose output

Sample Output

╔══════════════════════════════════════════════════════════════════╗
β•‘        NullSec KotlinGuard - Container Security Scanner          β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

[Demo Mode]

Scanning container security configurations...

Scanning Docker Containers...

═══════════════════════════════════════════════════════════════════
  Resource: Container: vulnerable-web

  Findings (8):

  [CRITICAL] Privileged Container
      ID:          PRIV-001
      Resource:    Security Context
      MITRE:       T1611
      Remediation: Disable privileged mode and use specific capabilities

  [CRITICAL] Sensitive Path Mounted: /var/run/docker.sock
      ID:          VOL-a1b2
      Resource:    Volume: /var/run/docker.sock
      MITRE:       T1611
      Remediation: Remove mount to /var/run/docker.sock

  [HIGH] Dangerous Capability: SYS_ADMIN
      ID:          CAP-c3d4
      Resource:    Capabilities
      MITRE:       T1611
      Remediation: Remove capability SYS_ADMIN unless absolutely required

  [HIGH] Sensitive Path Mounted: /etc/shadow
      ID:          VOL-e5f6
      Resource:    Volume: /host/shadow
      MITRE:       T1552
      Remediation: Remove mount to /etc/shadow or use read-only mode

  [MEDIUM] Sensitive Data in Environment: DB_PASSWORD
      ID:          ENV-1234
      Resource:    Environment: DB_PASSWORD
      MITRE:       T1552.001
      Remediation: Use secrets management instead of environment variables

═══════════════════════════════════════════════════════════════════
  Resource: Container: secure-api

  βœ“ No security issues found in secure-api

Scanning Kubernetes Resources...

═══════════════════════════════════════════════════════════════════
  Resource: Deployment: default/vulnerable-deployment

  Findings (5):

  [CRITICAL] Privileged Container: main
      ID:          K8S-PRIV-001
      Resource:    default/vulnerable-deployment/main
      MITRE:       T1611
      Remediation: Set privileged: false

  [HIGH] Host Network Enabled
      ID:          K8S-NET-001
      Resource:    default/vulnerable-deployment
      MITRE:       T1557
      Remediation: Disable hostNetwork unless required

  [HIGH] Host PID Enabled
      ID:          K8S-PID-001
      Resource:    default/vulnerable-deployment
      MITRE:       T1611
      Remediation: Disable hostPID

═══════════════════════════════════════════════════════════════════

  Summary:
    Resources Scanned: 5
    Clean:             2
    Total Findings:    16
    Critical:          4
    High:              7
    Medium:            4
    Low:               1

Code Highlights

Sealed Classes for Exhaustive Matching

sealed class ScanResult {
    data class Vulnerable(val findings: List<Finding>) : ScanResult()
    data class Clean(val message: String) : ScanResult()
    data class Error(val error: String) : ScanResult()
}

// Compiler ensures all cases are handled
when (result) {
    is ScanResult.Vulnerable -> printFindings(result.findings)
    is ScanResult.Clean -> println(result.message)
    is ScanResult.Error -> println(result.error)
}

Data Classes - Immutable Value Objects

data class Finding(
    val id: String,
    val severity: Severity,
    val title: String,
    val description: String,
    val resource: String,
    val mitreId: String,
    val remediation: String,
    val cveId: String? = null  // Null-safe optional
)

Extension Functions

fun List<Finding>.countBySeverity(severity: Severity): Int =
    count { it.severity == severity }

fun List<Finding>.sortedBySeverity(): List<Finding> =
    sortedByDescending { it.severity.toInt() }

// Usage
val criticalCount = findings.countBySeverity(Severity.Critical)
val sorted = findings.sortedBySeverity()

Collection Builders

fun scanContainer(container: Container): ScanResult {
    val findings = buildList {
        SecurityRules.checkPrivileged(container.privileged)?.let { add(it) }
        addAll(SecurityRules.checkCapabilities(container.capabilities))
        addAll(SecurityRules.checkMounts(container.volumes))
        addAll(SecurityRules.checkEnvironment(container.env))
    }
    
    return if (findings.isEmpty()) {
        ScanResult.Clean("No security issues found")
    } else {
        ScanResult.Vulnerable(findings.sortedBySeverity())
    }
}

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               KotlinGuard Architecture                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
β”‚   β”‚  Docker API      β”‚    β”‚  Kubernetes API  β”‚               β”‚
β”‚   β”‚  (Containers)    β”‚    β”‚  (Resources)     β”‚               β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β”‚            β”‚                       β”‚                          β”‚
β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚                        β”‚                                       β”‚
β”‚                        β–Ό                                       β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚           Data Classes (Immutable)                β”‚        β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚        β”‚
β”‚   β”‚  β”‚ Container   β”‚ β”‚ K8sResource β”‚ β”‚ Finding     β”‚ β”‚        β”‚
β”‚   β”‚  β”‚ (data)      β”‚ β”‚ (data)      β”‚ β”‚ (data)      β”‚ β”‚        β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                            β”‚                                   β”‚
β”‚                            β–Ό                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚           SecurityRules (object)                  β”‚        β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚        β”‚
β”‚   β”‚  β”‚ Capabilitiesβ”‚ β”‚ Mounts      β”‚ β”‚ Environment β”‚ β”‚        β”‚
β”‚   β”‚  β”‚ Check       β”‚ β”‚ Check       β”‚ β”‚ Check       β”‚ β”‚        β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                            β”‚                                   β”‚
β”‚                            β–Ό                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
β”‚   β”‚  ScanResult      β”‚    β”‚  Report          β”‚               β”‚
β”‚   β”‚  (sealed class)  │───▢│  Generator       β”‚               β”‚
β”‚   β”‚  Vulnerable |    β”‚    β”‚                  β”‚               β”‚
β”‚   β”‚  Clean | Error   β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚                                                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why Kotlin?

Requirement Kotlin Advantage
Type Safety Sealed classes, null safety
Expressiveness Extension functions
Immutability Data classes
Conciseness Type inference
Interop Full Java compatibility
Multiplatform JVM, Native, JS targets

License

MIT License - See LICENSE for details.

Related Tools

About

πŸ›‘οΈ Container and Kubernetes security scanner with sealed classes and data classes - Kotlin

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages