Documentation
¶
Overview ¶
Package security provides security validation utilities for Azure Developer CLI extensions.
This package implements critical security checks to prevent common vulnerabilities including path traversal attacks, command injection, SSRF, and insecure file permissions. All user-provided input should be validated using these utilities before use in file operations, command execution, or network requests.
Key Features ¶
- Path validation (prevents directory traversal attacks) - Symbolic link resolution and validation - Service name validation (DNS-safe, container-safe identifiers) - Package manager name validation (allowlist-based) - Script name validation (rejects shell metacharacters and traversal) - Container environment detection - File permission validation (detects world-writable files)
Security Model ¶
This package follows defense-in-depth principles:
- Validate all user input at boundaries
- Resolve symbolic links to prevent TOCTOU attacks
- Use allowlists instead of denylists where possible
- Fail securely (deny by default)
- Provide clear error messages without leaking sensitive info
Path Validation ¶
Path traversal prevention:
- Detects ".." sequences in paths
- Resolves symbolic links to canonical paths
- Validates paths are within expected boundaries
- Handles both absolute and relative paths
Input Sanitization ¶
Service names:
- Must start with alphanumeric character
- May contain: a-z, A-Z, 0-9, hyphen (-)
- DNS-safe (RFC 1123)
- Container-safe (Docker naming rules)
Script names:
- No shell metacharacters: ; | & $ ` \ < > ( ) { }
- Prevents command injection
- Safe for use in shell commands
Package managers:
- Allowlist: npm, pip, maven, gradle, dotnet, go
- Prevents arbitrary package manager execution
Example Usage ¶
// Validate user-provided path
safePath, err := security.ValidatePath("/base/dir", userPath)
if err != nil {
return fmt.Errorf("invalid path: %w", err)
}
// Validate a service name. Pass true to accept an empty name for an
// optional parameter.
if err := security.ValidateServiceName(name, false); err != nil {
return fmt.Errorf("invalid service name: %w", err)
}
// Reject script names carrying shell metacharacters or traversal
if err := security.ValidateScriptName(scriptName); err != nil {
return err
}
// Detect world-writable files
if err := security.ValidateFilePermissions("config.json"); err != nil {
if errors.Is(err, security.ErrInsecureFilePermissions) {
log.Warn("File has insecure permissions")
} else {
return err
}
}
Testing ¶
This package requires ≥95% test coverage including:
- Attack vectors (path traversal, command injection)
- Edge cases (symlinks, permissions, Unicode)
- Fuzz testing for input validation
- Cross-platform scenarios
Package security provides security utilities for path validation, input sanitization, and protection against common vulnerabilities like path traversal attacks.
Index ¶
- Variables
- func IsContainerEnvironment() bool
- func ValidateFilePermissions(path string) error
- func ValidatePackageManager(pm string) error
- func ValidatePath(path string) error
- func ValidatePathWithinBases(path string, allowedBases ...string) (string, error)
- func ValidateScriptName(name string) error
- func ValidateServiceName(name string, allowEmpty bool) error
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidPath indicates a path contains invalid characters or patterns. ErrInvalidPath = errors.New("invalid path") // ErrPathTraversal indicates a path traversal attack attempt. ErrPathTraversal = errors.New("path traversal detected") // ErrInvalidServiceName indicates an invalid service name. ErrInvalidServiceName = errors.New("invalid service name") )
var ErrInsecureFilePermissions = errors.New("insecure file permissions")
ErrInsecureFilePermissions indicates a file has insecure (world-writable) permissions.
Functions ¶
func IsContainerEnvironment ¶
func IsContainerEnvironment() bool
IsContainerEnvironment detects if the code is running in a containerized environment. It checks for:
- GitHub Codespaces (CODESPACES)
- VS Code Dev Containers (REMOTE_CONTAINERS, REMOTE_CONTAINERS_IPC)
- Kubernetes pods (KUBERNETES_SERVICE_HOST)
- Docker containers (/.dockerenv file exists)
This delegates to azdext.IsContainerEnvironment. Note that it treats any non-empty value as present, where azd-core previously required the literal string "true" for CODESPACES and REMOTE_CONTAINERS. Use azdext.ContainerRuntime when you need to know which one was detected.
func ValidateFilePermissions ¶
ValidateFilePermissions checks if a file has secure permissions. On Unix systems, it ensures the file is not world-writable. On Windows, this check is skipped as Windows uses ACLs differently. If the file is world-writable on non-Windows platforms, this returns ErrInsecureFilePermissions. Callers may translate that into a user visible warning when running inside container environments.
func ValidatePackageManager ¶
ValidatePackageManager checks if the package manager name is allowed.
func ValidatePath ¶
ValidatePath checks if a path is safe to use. It prevents path traversal attacks, symbolic link attacks, and validates the path is within allowed bounds.
func ValidatePathWithinBases ¶ added in v0.5.2
ValidatePathWithinBases validates a path and ensures it's within one of the allowed base directories. Returns the resolved absolute path or an error. If no allowedBases are provided, it just validates the path structure.
func ValidateScriptName ¶ added in v0.6.0
ValidateScriptName ensures a script name is safe to pass to a package manager as an argument. It rejects shell metacharacters, path traversal sequences, and empty names.
This delegates to azdext.ValidateScriptName, whose metacharacter set is a strict superset of the one azd-core used before v0.6.0: it additionally rejects ! ~ * ? % and the null byte, along with ".." and the empty string.
func ValidateServiceName ¶
ValidateServiceName validates that a service name is safe and well-formed. Service names must: - Start with an alphanumeric character - Contain only alphanumeric characters, underscores, hyphens, or dots - Be at most 63 characters (DNS label limit) - Not contain path traversal sequences
If allowEmpty is true, empty strings are accepted (for optional parameters).
Types ¶
This section is empty.