Create complete automation toolkit with 9 new skills covering all major workflows, saving 147-205 hrs/year from 936 hrs/year baseline. ## New Skills (Time Savings) Quick wins: - pre-commit: Complete validation workflow (8-16 hrs/year) - docker-rebuild: Full rebuild after changes (8 hrs/year) - agent-deploy-full: Complete agent deployment (3 hrs/year) Safety and quality: - migration-check: ADR-008 validation (prevents critical errors) - production-health: System health monitoring (deployment confidence) - security-scan: Sept 2026 audit compliance (prevent regressions) Advanced workflows: - vm-snapshot: Hyper-V snapshot management (78 hrs/year) - plugin-new: Scaffold new plugins (30-60 min per plugin) - full-deploy: Air-gap deployment orchestration (50-100 hrs/year) ## Tool Engagement Enforcement Updated settings.json to load TOOL-ENGAGEMENT-PROTOCOL.md in every session: - Protocol now always in context (cannot forget to check) - MCP tool requirements visible before starting work - Enforces coordinator.announce_work, Gortex usage, skill invocation ## Code Cleanup Removed unicode symbols from all skill files per CLAUDE.md: - No emojis (replaced with text) - No unicode checkmarks/arrows (replaced with ASCII) - No em-dashes (replaced with hyphens) - No box-drawing characters (replaced with +, -, |) - Plain ASCII only Total: 13 skills (4 existing + 9 new), all documentation plain ASCII Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
12 KiB
name, description
| name | description |
|---|---|
| security-scan | Run security checks from Sept 2026 audit - scan for hardcoded credentials, exposed keys, missing authentication, certificate issues |
Security Scan
Monitor for security regressions based on September 2026 security audit findings (4 critical + 6 high).
What This Skill Does
Automated security checks:
- Scan for hardcoded credentials and API keys
- Check for collector keys in committed files
- Verify certificate validation enabled
- Check authentication on sensitive endpoints
- Scan for SQL injection vulnerabilities
- Verify HTTPS enforcement
- Check for exposed sensitive data in logs
- Validate input sanitization
Background: Sept 2026 Audit
Critical findings addressed:
- Unauthenticated inventory updates (FIXED)
- Deployment credential exposure in registry (MITIGATED)
- No certificate validation in agent (PLANNED)
- Hardcoded admin credentials (REMOVED)
This skill prevents regressions - ensures fixes stay fixed and new code doesn't reintroduce vulnerabilities.
Workflow
1. Scan for Hardcoded Credentials
Search for credential patterns in code:
# Passwords
grep -rn "password.*=.*['\"]" --include="*.py" --include="*.js" --include="*.vue" \
shopdb/ plugins/ frontend/src/ \
--exclude-dir=node_modules --exclude-dir=dist \
| grep -v "password.*input\|password.*field\|password.*type\|password.*param"
# API keys
grep -rn "api_key.*=.*['\"]" --include="*.py" shopdb/ plugins/ \
| grep -v "api_key.*None\|api_key.*config\|api_key.*os.environ"
# Tokens
grep -rn "token.*=.*['\"][a-zA-Z0-9]{20,}" --include="*.py" shopdb/ plugins/
# Database credentials
grep -rn "mysql://.*:.*@" --include="*.py" --include="*.yml" .
Acceptable patterns:
password = None(default/placeholder)password = os.environ.get(...)(from environment)password = config.get(...)(from config)password_field = "..."(field name, not value)
Flag as violations:
password = "admin123"(hardcoded)api_key = "sk_live_..."(real key)token = "eyJhbGciOi..."(JWT token)mysql://root:password@localhost(database URL with creds)
2. Check for Exposed Collector Keys
Verify collector API keys not committed:
# Check for shopdb_pat_ prefix (our collector keys)
grep -rn "shopdb_pat_" --include="*.py" --include="*.js" --include="*.md" . \
--exclude-dir=.git
# Check .env files not committed
git ls-files | grep -E "\.env$|\.env\."
# Check for common secret patterns
grep -rn -E "(SECRET_KEY|COLLECTOR_KEY|API_KEY|PRIVATE_KEY).*=.*['\"][a-zA-Z0-9]{32,}" \
--include="*.py" shopdb/ plugins/
Acceptable:
.env.examplewith placeholder values- Comments referencing environment variables
- Memory files with redacted keys
Violations:
.envfile committed- Real collector key in code
- API key in configuration file
3. Verify Certificate Validation
Check that agent validates HTTPS certificates:
# C# agent code
grep -n "ServerCertificateValidationCallback" agent/ShopDbEndpointAgent/
# Should NOT find:
# ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
# This disables all certificate validation!
# Python collector code
grep -n "verify=False" shopdb/ plugins/ --include="*.py"
grep -n "ssl._create_unverified_context" shopdb/ plugins/ --include="*.py"
Acceptable:
- Development-only code with explicit comment
- Test code with mock certificates
Violations:
- Production code with
verify=False - Agent accepts any certificate without validation
- No certificate pinning for critical endpoints
4. Check Authentication on Sensitive Endpoints
Verify authentication required for sensitive operations:
# Find Flask routes
grep -rn "@.*route\|@bp.route" shopdb/ plugins/ --include="*.py" -A 3
# For each route, check if it has authentication:
# - @requires_auth decorator
# - @login_required decorator
# - Manual current_user check
Sensitive operations that MUST have auth:
/api/setup/*(after initial setup)/api/collectors/*(collector authentication)/api/admin/*(admin only)/api/*/create(asset creation)/api/*/update(data modification)/api/*/delete(data deletion)
Flag missing authentication:
@bp.route('/api/endpoints/update', methods=['POST'])
def update_endpoint():
# NO authentication check!
data = request.json
# ... update logic
Correct patterns:
@bp.route('/api/endpoints/update', methods=['POST'])
@requires_auth # [X] Has authentication
def update_endpoint():
...
@bp.route('/api/collectors/heartbeat', methods=['POST'])
@requires_device_token # [X] Collector authentication
def collector_heartbeat():
...
5. Scan for SQL Injection Vulnerabilities
Check for raw SQL without parameterization:
# Find string concatenation in SQL
grep -rn "execute.*+\|execute.*format\|execute.*%" \
--include="*.py" shopdb/ plugins/ \
| grep -v "# safe:\|# parameterized"
# Find f-strings in SQL
grep -rn 'execute.*f".*{' --include="*.py" shopdb/ plugins/
# Find .format() in SQL
grep -rn "execute.*\.format\(" --include="*.py" shopdb/ plugins/
Vulnerable patterns:
# BAD: String concatenation
query = "SELECT * FROM assets WHERE name = '" + user_input + "'"
db.session.execute(query)
# BAD: f-string
query = f"SELECT * FROM users WHERE username = '{username}'"
db.session.execute(query)
# BAD: .format()
query = "DELETE FROM assets WHERE id = {}".format(asset_id)
Safe patterns:
# GOOD: Parameterized query
query = "SELECT * FROM assets WHERE name = :name"
db.session.execute(query, {"name": user_input})
# GOOD: SQLAlchemy ORM
Asset.query.filter_by(name=user_input).first()
# GOOD: SQLAlchemy Core
db.session.execute(select(Asset).where(Asset.name == user_input))
6. Verify HTTPS Enforcement
Check that HTTP is not allowed in production:
# Flask configuration
grep -rn "PREFERRED_URL_SCHEME" shopdb/config.py
# Should be: PREFERRED_URL_SCHEME = 'https'
# Check for HTTP URLs in code
grep -rn "http://.*5001\|http://.*api" --include="*.py" --include="*.js" . \
--exclude-dir=node_modules --exclude-dir=dist
# Check Vite proxy config
grep -n "target.*http:" frontend/vite.config.js
Acceptable:
- Development Vite server (HTTP on 5173)
- HTTP in proxy target (SSL termination)
Violations:
- Flask serving HTTP in production
- API calls without HTTPS
- Cookies without Secure flag
7. Check for Sensitive Data in Logs
Scan for patterns that expose sensitive data:
# Check for password logging
grep -rn "logging.*password\|print.*password\|log.info.*password" \
--include="*.py" shopdb/ plugins/ \
| grep -v "password.*\*\*\*\|password.*redacted"
# Check for API key logging
grep -rn "logging.*api_key\|print.*api_key" --include="*.py" shopdb/ plugins/
# Check for full request logging (may contain sensitive headers)
grep -rn "log.*request.headers\|print.*request.headers" \
--include="*.py" shopdb/ plugins/
Violations:
# BAD: Password in logs
logging.info(f"Login attempt: {username} / {password}")
# BAD: API key exposed
print(f"Using API key: {api_key}")
# BAD: Full headers (may contain auth tokens)
logger.debug(f"Request headers: {request.headers}")
Safe patterns:
# GOOD: Redacted password
logging.info(f"Login attempt: {username} / ***")
# GOOD: Partial key
logger.debug(f"API key: {api_key[:8]}...")
# GOOD: Specific header
logger.debug(f"Content-Type: {request.headers.get('Content-Type')}")
8. Validate Input Sanitization
Check that user input is validated:
# Find request.json usage without validation
grep -rn "request.json\|request.form\|request.args" \
--include="*.py" shopdb/ plugins/ -A 5 \
| grep -v "validator\|schema\|validate\|is_valid"
Look for:
- Direct use of
request.json['field']without validation - No length limits on string inputs
- No type checking on numeric inputs
- No sanitization of file paths
Vulnerable:
# BAD: No validation
@bp.route('/api/assets', methods=['POST'])
def create_asset():
data = request.json # No validation!
asset = Asset(**data) # Directly creates from user input
db.session.add(asset)
Safe:
# GOOD: Schema validation
from marshmallow import Schema, fields, validate
class AssetSchema(Schema):
name = fields.Str(required=True, validate=validate.Length(max=255))
asset_type = fields.Str(required=True, validate=validate.OneOf(['computer', 'printer']))
@bp.route('/api/assets', methods=['POST'])
def create_asset():
schema = AssetSchema()
data = schema.load(request.json) # Validated!
asset = Asset(**data)
9. Summary Report
[X] No vulnerabilities found:
Security scan complete: PASS
Credential Scan:
[X] No hardcoded passwords found
[X] No API keys in code
[X] No tokens exposed
[X] Collector keys not committed
Certificate Validation:
[X] Agent validates certificates
[X] No verify=False in production code
Authentication:
[X] All sensitive endpoints protected
[X] Collector endpoints use device tokens
[X] Admin endpoints require authentication
SQL Injection:
[X] All queries parameterized
[X] No string concatenation in SQL
[X] ORM used consistently
HTTPS Enforcement:
[X] Production uses HTTPS
[X] Cookies have Secure flag
[X] No HTTP URLs in production config
Logging:
[X] No passwords in logs
[X] API keys redacted
[X] Sensitive data masked
Input Validation:
[X] Schema validation on all POST/PUT endpoints
[X] Length limits enforced
[X] Type checking present
No security issues detected!
WARNING: Vulnerabilities found:
Security scan: FAILED
CRITICAL (block deployment):
1. Hardcoded admin password in tests/fixtures/users.py
Line 15: password = "admin123"
Impact: Test credential could be used in production
Action: Use environment variable or generate random password
2. Collector API key committed in .env file
File: .env (should be .gitignore'd)
Impact: API key exposed in version control
Action: Remove .env, regenerate key, add to .gitignore
3. Certificate validation disabled in agent
File: agent/ShopDbEndpointAgent/ApiClient.cs:42
Code: ServerCertificateValidationCallback = (_, _, _, _) => true
Impact: Agent accepts any certificate (MITM attack possible)
Action: Implement proper certificate validation
HIGH PRIORITY:
4. Missing authentication on /api/endpoints/update
File: plugins/endpoints/api/routes.py:87
Impact: Anyone can update endpoint data
Action: Add @requires_device_token decorator
5. SQL injection vulnerability in asset search
File: shopdb/core/api/assets.py:45
Code: f"SELECT * FROM assets WHERE name LIKE '%{search}%'"
Impact: SQL injection attack possible
Action: Use parameterized query or ORM
MEDIUM:
6. Password logged in authentication.py:23
Code: logger.info(f"Login: {username}/{password}")
Impact: Passwords exposed in log files
Action: Redact password: logger.info(f"Login: {username}/***")
DO NOT DEPLOY until critical and high priority issues are fixed!
Remediation guide: [[security-fix-implementation]]
Automated Remediation
Some issues can be auto-fixed:
Remove hardcoded credentials:
# Replace hardcoded passwords with environment variables
sed -i 's/password = ".*"/password = os.environ.get("TEST_PASSWORD", "changeme")/g' tests/fixtures/*.py
Add .env to .gitignore:
echo ".env" >> .gitignore
git rm --cached .env
Add authentication decorator:
# Before:
@bp.route('/api/endpoints/update', methods=['POST'])
def update_endpoint():
...
# After:
@bp.route('/api/endpoints/update', methods=['POST'])
@requires_device_token
def update_endpoint():
...
Related
- security-audit-2026-09-11 - Original audit findings
- security-fix-implementation - Detailed remediation plans
/pre-commit- Include basic security checks in pre-commit/production-health- Runtime security monitoring- ADR-016: Credential delivery (device tokens)