Back to skill

Security audit

Security Monitor

Security checks for vulnerabilities and agentic risk

Overview

This security monitor is mostly aligned with its purpose, but it reads a root credential file, ignores the documented threat scoping option, and can run too aggressively in daemon mode due to broken interval parsing.

Review before installing. Run only under a tightly scoped account, avoid granting access to unrelated credential files, do not rely on --threats to limit what it checks, and avoid daemon mode until interval parsing and resource controls are fixed. Treat its logs and state files as sensitive security data.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/monitor.cjs:189
Finding

Unnecessarily Broad Access to a Sensitive Environment File

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/monitor.cjs:289
Finding

Broken Interval Parsing Can Cause a Near-Continuous Monitoring Loop

Content
View full analysis
a.startsWith('--interval='))?.[1] || args.find(a => a.startsWith('--interval '))?.[1] || '60'), daemon: args.includes('--daemon'), threats: args.find(a => a.startsWith('--threats='))?.[1] || 'all' }; ``` ### Technical Analysis The parser treats a complete command-line argument as though it were an array containing the parsed option value. For an argument such as `--interval=60`, the expression: ```js args.find(a => a.startsWith('--interval='))?.[1] ``` returns the character at index `1`, which is `-`, rather than `60`. `parseInt('-')` consequently produces `NaN`. The documented space-separated form, `--interval 60`, is also not parsed correctly. `process.argv.slice(2)` produces separate elements (`"--interval"` and `"60"`), so no single argument starts with `"--interval "`. No validation verifies that the resulting interval is finite, positive, or within a safe operational range before it is passed to `setInterval`. A non-finite or very small delay can be normalized by the Node.js timer implementation to a minimal delay. In daemon mode, this can repeatedly execute authentication-log, port, process, file, API-key, and Docker checks while also writing monitor state and alerts. ### Attack Path 1. An operator starts the monitor using the documented command, such as: ```bash node scripts/monitor.cjs --daemon --interval=60 ``` 2. The parser selects the second character of `--interval=60`, producing `-`. 3. `parseInt('-')` produces `NaN`. 4. `interval * 1000` remains `NaN`. 5. The invalid delay is supplied to `setI ...[truncated 1062 chars]
Remediation
View remediation
arg.startsWith('--interval=')); const separateIndex = args.indexOf('--interval'); const rawInterval = equalArg ? equalArg.slice('--interval='.length) : separateIndex >= 0 ? args[separateIndex + 1] : '60'; const interval = Number(rawInterval); if (!Number.isInteger(interval) || interval < 1 || interval > 86400) { throw new Error('Interval must be an integer between 1 and 86400 seconds'); } ``` Additional hardening should include: - Fail closed instead of silently accepting malformed input. - Impose a conservative minimum interval suitable for the cost of the checks. - Use a non-overlapping scheduling model, such as scheduling the next run only after the current run finishes. - Add tests for `--interval=60`, `--interval 60`, missing values, negative numbers, zero, decimals, `NaN`, and excessively large values. - Apply process-level resource limits when operating as a daemon. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/monitor.cjs:225
Finding

Threat Selection Is Ignored and All Monitoring Checks Always Execute

Content
View full analysis
{ const now = Date.now(); console.log(`\n[${new Date().toISOString()}] Running security checks...`); checkFailedLogins(); checkOpenPorts(); checkProcessAnomalies(); checkFileChanges(); checkApiKeyUsage(); checkDockerHealth(); ``` ### Technical Analysis The `threats` option is accepted and displayed to the user but is never used to control which checks run. Every invocation executes all six checks, including authentication-log inspection, port enumeration, process enumeration, sensitive environment-file access, file timestamp inspection, and Docker status queries. This contradicts the documented `--threats=credentials,ports,api-calls` behavior and prevents operators from limiting the monitor to an approved scope. The output can misleadingly indicate that only selected threats are monitored while the implementation performs broader system reconnaissance and accesses additional resources. This is particularly significant where permissions were gran ...[truncated 1388 chars]
Remediation
View remediation
value.trim()).filter(Boolean); for (const threat of selected) { if (!Object.hasOwn(checks, threat)) { throw new Error(`Unknown threat type: ${threat}`); } checks[threat](); } ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/monitor.cjs (reported line 173)May include surrounding context.

js
function checkFileChanges() {
  // Check for unexpected file changes
  const watchPaths = [
    '/root/clawd/skills/.env',
    '/root/clawd/config',
    '/root/clawd/.env'
  ];

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/monitor.cjs (reported line 175)May include surrounding context.

js
function checkFileChanges() {
  // Check for unexpected file changes
  const watchPaths = [
    '/root/clawd/skills/.env',
    '/root/clawd/config',
    '/root/clawd/.env'
  ];

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

At this line the script directly reads /root/clawd/skills/.env, which is a credential-bearing file. Direct secret-file access by a continuously running monitor significantly increases the blast radius of any compromise of the monitor process and is especially concerning here because the stated purpose can be achieved without reading raw credentials.

Content

Scanner excerpt · scripts/monitor.cjs (reported line 205)May include surrounding context.

js
// This is a simplified check - real implementation would need API integration
  
  try {
    const envContent = fs.readFileSync('/root/clawd/skills/.env', 'utf8');
    
    if (envContent.includes('TWITTER') || envContent.includes('KAPSO')) {
      log('INFO', 'API credentials present', {

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill advertises Telegram alerts without warning that security event data may be sent to a third-party service. In a security-monitoring context, alerts can include sensitive metadata about hosts, credentials usage patterns, or incidents, so undisclosed external transmission increases privacy and operational security risk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest description promises detection of unusual API calls and credential usage patterns. In code, the only API-related logic reads an environment file and logs whether certain service names appear, which does not analyze API call behavior or usage patterns.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The monitor reads a sensitive .env file and inspects its contents to infer which credential-bearing services are configured. That exceeds simple health monitoring and unnecessarily accesses secrets, increasing exposure risk if the process, logs, state, or future code paths are compromised. In this skill context, a security monitor should minimize secret access, so this behavior is more dangerous than in a credential-management tool.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script reads a sensitive credential file without any necessity visible to the user and without a clear disclosure or least-privilege boundary. Even though it currently only searches for service names, accessing secret-bearing files widens the trust boundary and can lead to accidental exposure through future debugging, crashes, or feature creep.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This markdown file states that JSON logs are written to /root/clawd/clawdbot-security/logs/alerts.log, which is a file write affecting local system state. Under the markdown criteria for missing user warnings, the description should explicitly warn users that monitoring results will be persisted on disk, especially at a privileged-looking path, rather than only listing it as output.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/monitor.cjs:79