Security
Dyngle is designed for workflow automation, but understanding its security characteristics is important for safe usage.
Command Execution Model
No Shell Interpretation
Commands are executed directly using Python's subprocess.run() with arguments parsed in a shell-like fashion:
Safe:
- Arguments are passed as separate parameters to the subprocess
- No shell meta-characters are interpreted (
|,>,&&,;, etc.) - Environment variables are not automatically expanded
This reduces common shell injection risks:
dyngle:
operations:
safe-example:
- echo "User input: {{user-input}}"
- curl "{{url}}"
Even if user-input contains shell meta-characters, they won't be interpreted as shell commands.
Template Substitution
Templates are evaluated before commands are executed:
dyngle:
operations:
example:
- echo "Hello {{name}}"
Security implications:
- Template values are substituted as strings
- Values from untrusted sources could still inject command arguments
- Validate and sanitize external inputs before use
Configuration Security
Not Robust to Malicious Configuration
Important: Dyngle is not designed to be robust against malicious configuration files.
- Configuration files contain Python expressions that are evaluated
- Expressions have access to system capabilities (file operations, networking, etc.)
- Only use configuration files from trusted sources
Never run Dyngle with untrusted configuration files.
Configuration File Permissions
Protect your configuration files:
# Set appropriate permissions
chmod 600 ~/.dyngle.yml
chmod 600 .dyngle.yml
This is especially important if your configuration contains:
- Credentials or API keys
- Sensitive operation logic
- Private operations that manage secrets
Expression Evaluation
Python Execution Context
Expressions are evaluated in a restricted Python context:
Available:
- Read-only operations (mostly)
- Standard library modules (
datetime,math, etc.) - Limited file system access via
Path()(current directory only)
Security notes:
- Expressions can still perform many operations
- The restriction is not a security sandbox
- Malicious expressions could cause harm
Path() Restrictions
The Path() function in expressions is restricted to the current working directory:
dyngle:
expressions:
config: "Path('.dyngle.yml')" # OK
# bad: "Path('/etc/passwd')" # Error
This prevents expressions from accessing arbitrary filesystem locations.
MCP Server Security
Tool Exposure
When running as an MCP server, operations become accessible to AI assistants:
Public operations:
- Exposed as tools
- Can be called by AI assistants
- May be called with unexpected inputs
Private operations:
- Not exposed via MCP
- Cannot be called by AI assistants
- Useful for sensitive operations
Best Practices for MCP
- Use access control:
dyngle:
operations:
get-secret:
access: private # Not exposed
return: secret
steps:
- aws secretsmanager get-secret-value --secret-id api-key => secret
public-operation:
description: Safe operation
steps:
- sub: get-secret
=> secret
- curl -H "Authorization: {{secret}}" https://api.example.com
- Validate inputs:
dyngle:
operations:
deploy:
description: Deploy to environment
expressions:
valid-env: "args[0] if args[0] in ['staging', 'production'] else None"
steps:
- echo "Deploying to {{valid-env}}"
- Limit operation scope:
- Don't expose operations that can modify critical systems
- Consider read-only operations for MCP exposure
- Use private sub-operations for sensitive steps
Secrets Management
Avoid Hardcoded Secrets
Bad:
dyngle:
values:
api-key: secret-key-123 # Never do this
Better:
dyngle:
operations:
get-api-key:
access: private
return: key
steps:
- aws secretsmanager get-secret-value --secret-id api-key => secret
- secret -> jq -r '.SecretString' => key
Use Private Operations
Operations that handle secrets should be private:
dyngle:
operations:
fetch-credentials:
access: private
return: creds
steps:
- # Fetch from secure source
authenticated-operation:
steps:
- sub: fetch-credentials
=> creds
- # Use credentials
This prevents:
- Direct execution via
dyngle run - Exposure via
dyngle list-operations - Access through MCP server
Input Validation
Data from stdin
Data piped to operations should be validated:
dyngle:
operations:
process-user-data:
expressions:
validated-email: "email if '@' in email else '[email protected]'"
steps:
- echo "Processing: {{validated-email}}"
Command Arguments
Arguments passed to operations should be validated:
dyngle:
operations:
deploy:
expressions:
environment: "args[0] if args and args[0] in ['dev', 'staging', 'prod'] else None"
steps:
- echo "Deploying to {{environment}}"
General Best Practices
-
Principle of Least Privilege:
- Only expose necessary operations publicly
- Use private operations for internal logic
- Limit MCP tool exposure
-
Configuration Management:
- Store configurations in version control (without secrets)
- Use separate configs for different environments
- Protect configuration files with appropriate permissions
-
Secret Handling:
- Never hardcode secrets
- Use secret management services (AWS Secrets Manager, etc.)
- Keep secret-handling operations private
-
Input Validation:
- Validate all external inputs
- Use expressions to sanitize data
- Set reasonable defaults
-
Audit and Monitor:
- Review operations before exposing via MCP
- Monitor operation execution in production
- Keep audit logs when appropriate
Reporting Security Issues
If you discover a security vulnerability in Dyngle, please report it through the appropriate channels rather than creating public issues.