test: add cron-triggered Telegram reminder to soak test - #2519

Merged
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test
Mar 12, 2026
Merged

test: add cron-triggered Telegram reminder to soak test#2519
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test

Conversation

@AhmedTMM

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a cron reminder test to the Telegram soak test that verifies OpenClaw can stay alive and execute scheduled tasks on the VM
  • Installs a one-shot cron job (~55 min delay) before the 1h soak wait that sends a Telegram message, then verifies the send succeeded after the wait
  • Moves Telegram config injection before the soak wait so the cron has the bot token immediately
  • Soak test now runs 4 tests: getMe, sendMessage, getWebhookInfo, cron-fired reminder

How it works

  1. After provisioning + verification, inject Telegram bot token into OpenClaw config
  2. Install a cron script on the VM that sleeps 55 min then sends a Telegram message with a unique marker
  3. Script writes the Telegram API response to /tmp/spawn-cron-telegram-result.json
  4. After the 1h soak wait, read the result file and verify "ok":true

Test plan

  • Manual: Run SOAK_WAIT_SECONDS=120 SOAK_CRON_DELAY_SECONDS=60 bash sh/e2e/e2e.sh --soak with short timers to verify the cron fires
  • Full soak: Trigger via ?reason=soak on the QA server to run the full 1h cycle

🤖 Generated with Claude Code

AhmedTMMand others added 3 commits March 11, 2026 23:50
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM marked this pull request as ready for review March 12, 2026 07:37
@AhmedTMM
AhmedTMMforce-pushed the soak/cron-telegram-test branch from 6283424 to 830e67dCompareMarch 12, 2026 07:47

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: CHANGES REQUESTED
Commit: 830e67d

Findings

CRITICAL - sh/e2e/lib/soak.sh:247-248 — Command injection via unquoted SOAK_CRON_DELAY_SECONDS

# VULNERABLE:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' ...")# FIX: Add quotes and validate
fire_at=$(cloud_exec "${app}""date -u -d '+\"${SOAK_CRON_DELAY_SECONDS}\" seconds' ...")

Attacker-controlled SOAK_CRON_DELAY_SECONDS='3300; rm -rf /' would execute arbitrary commands.

HIGH - sh/e2e/lib/soak.sh:20-21 — Missing input validation on numeric environment variables

SOAK_WAIT_SECONDS="${SOAK_WAIT_SECONDS:-3600}"
SOAK_CRON_DELAY_SECONDS="${SOAK_CRON_DELAY_SECONDS:-3300}"

These must be validated as positive integers before use in arithmetic or command construction.

HIGH - sh/e2e/lib/soak.sh:264-274 — Command injection via TELEGRAM_TEST_CHAT_ID in openclaw cron command
The TELEGRAM_TEST_CHAT_ID variable is interpolated into a command string and could contain shell metacharacters. Must be sanitized or validated to contain only alphanumeric/dash/underscore characters.

MEDIUM - sh/e2e/lib/soak.sh:243 — Arithmetic expansion with unvalidated input

$((SOAK_CRON_DELAY_SECONDS /60))

This will fail if SOAK_CRON_DELAY_SECONDS is not a valid integer. Add validation before arithmetic operations.

LOW - sh/e2e/lib/soak.sh:285 — Race condition with /tmp/.spawn-cron-scheduled
Using a fixed filename in /tmp could conflict if multiple soak tests run on the same VM. Consider using mktemp or including the app name in the marker filename.

Required Changes

  1. Add input validation function at the top of the file:
validate_numeric_env() {
local var_name="$1"local var_value="$2"if!printf'%s'"${var_value}"| grep -qE '^[0-9]+$';then
log_err "${var_name} must be a positive integer, got: ${var_value}"return 1
fiif [ "${var_value}"-lt 1 ] || [ "${var_value}"-gt 86400 ];then
log_err "${var_name} out of range (1-86400), got: ${var_value}"return 1
fireturn 0
}
  1. Validate environment variables after line 21:
if! validate_numeric_env "SOAK_WAIT_SECONDS""${SOAK_WAIT_SECONDS}";thenexit 1;fiif! validate_numeric_env "SOAK_CRON_DELAY_SECONDS""${SOAK_CRON_DELAY_SECONDS}";thenexit 1;fi
  1. Fix command injection on line 247-248 by properly quoting:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v+${SOAK_CRON_DELAY_SECONDS}S '+%Y-%m-%dT%H:%M:%SZ'"2>&1)||true

Note: Since these are now validated as numeric-only, the injection risk is mitigated, but proper quoting is still best practice.

  1. Validate TELEGRAM_TEST_CHAT_ID format in soak_validate_telegram_env (line 40):
if!printf'%s'"${TELEGRAM_TEST_CHAT_ID}"| grep -qE '^-?[0-9]+$';then
log_err "TELEGRAM_TEST_CHAT_ID must be numeric (chat IDs are integers)"
missing=1
fi
  1. Fix race condition on line 285:
cloud_exec "${app}""touch /tmp/.spawn-cron-scheduled-${app}"2>/dev/null ||true

Tests

  • bash -n: PASS
  • curl|bash: N/A (not a standalone installer)
  • macOS compat: OK (uses bash 3.x compatible patterns)

-- security/pr-reviewer

AhmedTMMand others added 2 commits March 12, 2026 00:51
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 40fe98f

Summary

All CRITICAL security issues from the prior review (commit 830e67d) have been resolved. The PR now includes comprehensive input validation that prevents command injection attacks.

Fixed Issues

  • CRITICAL → FIXED (Lines 32-48) — Added validate_positive_int() function with regex validation for SOAK_WAIT_SECONDS and SOAK_CRON_DELAY_SECONDS. Range check (1-86400) prevents extreme values. Validation happens before any command/arithmetic use.
  • CRITICAL → FIXED (Lines 66-68) — Added regex validation for TELEGRAM_TEST_CHAT_ID (pattern: ^-?[0-9]+$). Prevents injection via chat_id parameter in curl commands.
  • LOW (Lines 273-274, 311) — app parameter interpolated into commands without local validation. Mitigation: parameter comes from make_app_name() which should sanitize. Risk is LOW (requires attacker control of provisioning).

Tests

  • bash -n: PASS (no syntax errors)
  • bun test: N/A (no TypeScript changes)
  • curl|bash: OK (no relative paths, self-contained functions)
  • macOS compat: OK (no echo -e, source <(...), ((var++)), or set -u)

Security Properties

✓ Input validation for all user-controlled numeric parameters
✓ Regex-based validation prevents injection via special characters
✓ Base64 encoding used for sensitive tokens
✓ No new security issues introduced


-- security/pr-reviewer

@louisgv
louisgv merged commit 5b5e7d4 into OpenRouterLabs:mainMar 12, 2026
5 checks passed
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 12, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM deleted the soak/cron-telegram-test branch April 7, 2026 00:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AhmedTMM@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

test: add cron-triggered Telegram reminder to soak test - #2519

Merged
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test
Mar 12, 2026
Merged

test: add cron-triggered Telegram reminder to soak test#2519
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test

Conversation

@AhmedTMM

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a cron reminder test to the Telegram soak test that verifies OpenClaw can stay alive and execute scheduled tasks on the VM
  • Installs a one-shot cron job (~55 min delay) before the 1h soak wait that sends a Telegram message, then verifies the send succeeded after the wait
  • Moves Telegram config injection before the soak wait so the cron has the bot token immediately
  • Soak test now runs 4 tests: getMe, sendMessage, getWebhookInfo, cron-fired reminder

How it works

  1. After provisioning + verification, inject Telegram bot token into OpenClaw config
  2. Install a cron script on the VM that sleeps 55 min then sends a Telegram message with a unique marker
  3. Script writes the Telegram API response to /tmp/spawn-cron-telegram-result.json
  4. After the 1h soak wait, read the result file and verify "ok":true

Test plan

  • Manual: Run SOAK_WAIT_SECONDS=120 SOAK_CRON_DELAY_SECONDS=60 bash sh/e2e/e2e.sh --soak with short timers to verify the cron fires
  • Full soak: Trigger via ?reason=soak on the QA server to run the full 1h cycle

🤖 Generated with Claude Code

AhmedTMMand others added 3 commits March 11, 2026 23:50
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM marked this pull request as ready for review March 12, 2026 07:37
@AhmedTMM
AhmedTMMforce-pushed the soak/cron-telegram-test branch from 6283424 to 830e67dCompareMarch 12, 2026 07:47

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: CHANGES REQUESTED
Commit: 830e67d

Findings

CRITICAL - sh/e2e/lib/soak.sh:247-248 — Command injection via unquoted SOAK_CRON_DELAY_SECONDS

# VULNERABLE:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' ...")# FIX: Add quotes and validate
fire_at=$(cloud_exec "${app}""date -u -d '+\"${SOAK_CRON_DELAY_SECONDS}\" seconds' ...")

Attacker-controlled SOAK_CRON_DELAY_SECONDS='3300; rm -rf /' would execute arbitrary commands.

HIGH - sh/e2e/lib/soak.sh:20-21 — Missing input validation on numeric environment variables

SOAK_WAIT_SECONDS="${SOAK_WAIT_SECONDS:-3600}"
SOAK_CRON_DELAY_SECONDS="${SOAK_CRON_DELAY_SECONDS:-3300}"

These must be validated as positive integers before use in arithmetic or command construction.

HIGH - sh/e2e/lib/soak.sh:264-274 — Command injection via TELEGRAM_TEST_CHAT_ID in openclaw cron command
The TELEGRAM_TEST_CHAT_ID variable is interpolated into a command string and could contain shell metacharacters. Must be sanitized or validated to contain only alphanumeric/dash/underscore characters.

MEDIUM - sh/e2e/lib/soak.sh:243 — Arithmetic expansion with unvalidated input

$((SOAK_CRON_DELAY_SECONDS /60))

This will fail if SOAK_CRON_DELAY_SECONDS is not a valid integer. Add validation before arithmetic operations.

LOW - sh/e2e/lib/soak.sh:285 — Race condition with /tmp/.spawn-cron-scheduled
Using a fixed filename in /tmp could conflict if multiple soak tests run on the same VM. Consider using mktemp or including the app name in the marker filename.

Required Changes

  1. Add input validation function at the top of the file:
validate_numeric_env() {
local var_name="$1"local var_value="$2"if!printf'%s'"${var_value}"| grep -qE '^[0-9]+$';then
log_err "${var_name} must be a positive integer, got: ${var_value}"return 1
fiif [ "${var_value}"-lt 1 ] || [ "${var_value}"-gt 86400 ];then
log_err "${var_name} out of range (1-86400), got: ${var_value}"return 1
fireturn 0
}
  1. Validate environment variables after line 21:
if! validate_numeric_env "SOAK_WAIT_SECONDS""${SOAK_WAIT_SECONDS}";thenexit 1;fiif! validate_numeric_env "SOAK_CRON_DELAY_SECONDS""${SOAK_CRON_DELAY_SECONDS}";thenexit 1;fi
  1. Fix command injection on line 247-248 by properly quoting:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v+${SOAK_CRON_DELAY_SECONDS}S '+%Y-%m-%dT%H:%M:%SZ'"2>&1)||true

Note: Since these are now validated as numeric-only, the injection risk is mitigated, but proper quoting is still best practice.

  1. Validate TELEGRAM_TEST_CHAT_ID format in soak_validate_telegram_env (line 40):
if!printf'%s'"${TELEGRAM_TEST_CHAT_ID}"| grep -qE '^-?[0-9]+$';then
log_err "TELEGRAM_TEST_CHAT_ID must be numeric (chat IDs are integers)"
missing=1
fi
  1. Fix race condition on line 285:
cloud_exec "${app}""touch /tmp/.spawn-cron-scheduled-${app}"2>/dev/null ||true

Tests

  • bash -n: PASS
  • curl|bash: N/A (not a standalone installer)
  • macOS compat: OK (uses bash 3.x compatible patterns)

-- security/pr-reviewer

AhmedTMMand others added 2 commits March 12, 2026 00:51
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 40fe98f

Summary

All CRITICAL security issues from the prior review (commit 830e67d) have been resolved. The PR now includes comprehensive input validation that prevents command injection attacks.

Fixed Issues

  • CRITICAL → FIXED (Lines 32-48) — Added validate_positive_int() function with regex validation for SOAK_WAIT_SECONDS and SOAK_CRON_DELAY_SECONDS. Range check (1-86400) prevents extreme values. Validation happens before any command/arithmetic use.
  • CRITICAL → FIXED (Lines 66-68) — Added regex validation for TELEGRAM_TEST_CHAT_ID (pattern: ^-?[0-9]+$). Prevents injection via chat_id parameter in curl commands.
  • LOW (Lines 273-274, 311) — app parameter interpolated into commands without local validation. Mitigation: parameter comes from make_app_name() which should sanitize. Risk is LOW (requires attacker control of provisioning).

Tests

  • bash -n: PASS (no syntax errors)
  • bun test: N/A (no TypeScript changes)
  • curl|bash: OK (no relative paths, self-contained functions)
  • macOS compat: OK (no echo -e, source <(...), ((var++)), or set -u)

Security Properties

✓ Input validation for all user-controlled numeric parameters
✓ Regex-based validation prevents injection via special characters
✓ Base64 encoding used for sensitive tokens
✓ No new security issues introduced


-- security/pr-reviewer

@louisgv
louisgv merged commit 5b5e7d4 into OpenRouterLabs:mainMar 12, 2026
5 checks passed
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 12, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM deleted the soak/cron-telegram-test branch April 7, 2026 00:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AhmedTMM@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test: add cron-triggered Telegram reminder to soak test - #2519

Merged
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test
Mar 12, 2026
Merged

test: add cron-triggered Telegram reminder to soak test#2519
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test

Conversation

@AhmedTMM

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a cron reminder test to the Telegram soak test that verifies OpenClaw can stay alive and execute scheduled tasks on the VM
  • Installs a one-shot cron job (~55 min delay) before the 1h soak wait that sends a Telegram message, then verifies the send succeeded after the wait
  • Moves Telegram config injection before the soak wait so the cron has the bot token immediately
  • Soak test now runs 4 tests: getMe, sendMessage, getWebhookInfo, cron-fired reminder

How it works

  1. After provisioning + verification, inject Telegram bot token into OpenClaw config
  2. Install a cron script on the VM that sleeps 55 min then sends a Telegram message with a unique marker
  3. Script writes the Telegram API response to /tmp/spawn-cron-telegram-result.json
  4. After the 1h soak wait, read the result file and verify "ok":true

Test plan

  • Manual: Run SOAK_WAIT_SECONDS=120 SOAK_CRON_DELAY_SECONDS=60 bash sh/e2e/e2e.sh --soak with short timers to verify the cron fires
  • Full soak: Trigger via ?reason=soak on the QA server to run the full 1h cycle

🤖 Generated with Claude Code

AhmedTMMand others added 3 commits March 11, 2026 23:50
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM marked this pull request as ready for review March 12, 2026 07:37
@AhmedTMM
AhmedTMMforce-pushed the soak/cron-telegram-test branch from 6283424 to 830e67dCompareMarch 12, 2026 07:47

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: CHANGES REQUESTED
Commit: 830e67d

Findings

CRITICAL - sh/e2e/lib/soak.sh:247-248 — Command injection via unquoted SOAK_CRON_DELAY_SECONDS

# VULNERABLE:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' ...")# FIX: Add quotes and validate
fire_at=$(cloud_exec "${app}""date -u -d '+\"${SOAK_CRON_DELAY_SECONDS}\" seconds' ...")

Attacker-controlled SOAK_CRON_DELAY_SECONDS='3300; rm -rf /' would execute arbitrary commands.

HIGH - sh/e2e/lib/soak.sh:20-21 — Missing input validation on numeric environment variables

SOAK_WAIT_SECONDS="${SOAK_WAIT_SECONDS:-3600}"
SOAK_CRON_DELAY_SECONDS="${SOAK_CRON_DELAY_SECONDS:-3300}"

These must be validated as positive integers before use in arithmetic or command construction.

HIGH - sh/e2e/lib/soak.sh:264-274 — Command injection via TELEGRAM_TEST_CHAT_ID in openclaw cron command
The TELEGRAM_TEST_CHAT_ID variable is interpolated into a command string and could contain shell metacharacters. Must be sanitized or validated to contain only alphanumeric/dash/underscore characters.

MEDIUM - sh/e2e/lib/soak.sh:243 — Arithmetic expansion with unvalidated input

$((SOAK_CRON_DELAY_SECONDS /60))

This will fail if SOAK_CRON_DELAY_SECONDS is not a valid integer. Add validation before arithmetic operations.

LOW - sh/e2e/lib/soak.sh:285 — Race condition with /tmp/.spawn-cron-scheduled
Using a fixed filename in /tmp could conflict if multiple soak tests run on the same VM. Consider using mktemp or including the app name in the marker filename.

Required Changes

  1. Add input validation function at the top of the file:
validate_numeric_env() {
local var_name="$1"local var_value="$2"if!printf'%s'"${var_value}"| grep -qE '^[0-9]+$';then
log_err "${var_name} must be a positive integer, got: ${var_value}"return 1
fiif [ "${var_value}"-lt 1 ] || [ "${var_value}"-gt 86400 ];then
log_err "${var_name} out of range (1-86400), got: ${var_value}"return 1
fireturn 0
}
  1. Validate environment variables after line 21:
if! validate_numeric_env "SOAK_WAIT_SECONDS""${SOAK_WAIT_SECONDS}";thenexit 1;fiif! validate_numeric_env "SOAK_CRON_DELAY_SECONDS""${SOAK_CRON_DELAY_SECONDS}";thenexit 1;fi
  1. Fix command injection on line 247-248 by properly quoting:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v+${SOAK_CRON_DELAY_SECONDS}S '+%Y-%m-%dT%H:%M:%SZ'"2>&1)||true

Note: Since these are now validated as numeric-only, the injection risk is mitigated, but proper quoting is still best practice.

  1. Validate TELEGRAM_TEST_CHAT_ID format in soak_validate_telegram_env (line 40):
if!printf'%s'"${TELEGRAM_TEST_CHAT_ID}"| grep -qE '^-?[0-9]+$';then
log_err "TELEGRAM_TEST_CHAT_ID must be numeric (chat IDs are integers)"
missing=1
fi
  1. Fix race condition on line 285:
cloud_exec "${app}""touch /tmp/.spawn-cron-scheduled-${app}"2>/dev/null ||true

Tests

  • bash -n: PASS
  • curl|bash: N/A (not a standalone installer)
  • macOS compat: OK (uses bash 3.x compatible patterns)

-- security/pr-reviewer

AhmedTMMand others added 2 commits March 12, 2026 00:51
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 40fe98f

Summary

All CRITICAL security issues from the prior review (commit 830e67d) have been resolved. The PR now includes comprehensive input validation that prevents command injection attacks.

Fixed Issues

  • CRITICAL → FIXED (Lines 32-48) — Added validate_positive_int() function with regex validation for SOAK_WAIT_SECONDS and SOAK_CRON_DELAY_SECONDS. Range check (1-86400) prevents extreme values. Validation happens before any command/arithmetic use.
  • CRITICAL → FIXED (Lines 66-68) — Added regex validation for TELEGRAM_TEST_CHAT_ID (pattern: ^-?[0-9]+$). Prevents injection via chat_id parameter in curl commands.
  • LOW (Lines 273-274, 311) — app parameter interpolated into commands without local validation. Mitigation: parameter comes from make_app_name() which should sanitize. Risk is LOW (requires attacker control of provisioning).

Tests

  • bash -n: PASS (no syntax errors)
  • bun test: N/A (no TypeScript changes)
  • curl|bash: OK (no relative paths, self-contained functions)
  • macOS compat: OK (no echo -e, source <(...), ((var++)), or set -u)

Security Properties

✓ Input validation for all user-controlled numeric parameters
✓ Regex-based validation prevents injection via special characters
✓ Base64 encoding used for sensitive tokens
✓ No new security issues introduced


-- security/pr-reviewer

@louisgv
louisgv merged commit 5b5e7d4 into OpenRouterLabs:mainMar 12, 2026
5 checks passed
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 12, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM deleted the soak/cron-telegram-test branch April 7, 2026 00:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AhmedTMM@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test: add cron-triggered Telegram reminder to soak test - #2519

Merged
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test
Mar 12, 2026
Merged

test: add cron-triggered Telegram reminder to soak test#2519
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test

Conversation

@AhmedTMM

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a cron reminder test to the Telegram soak test that verifies OpenClaw can stay alive and execute scheduled tasks on the VM
  • Installs a one-shot cron job (~55 min delay) before the 1h soak wait that sends a Telegram message, then verifies the send succeeded after the wait
  • Moves Telegram config injection before the soak wait so the cron has the bot token immediately
  • Soak test now runs 4 tests: getMe, sendMessage, getWebhookInfo, cron-fired reminder

How it works

  1. After provisioning + verification, inject Telegram bot token into OpenClaw config
  2. Install a cron script on the VM that sleeps 55 min then sends a Telegram message with a unique marker
  3. Script writes the Telegram API response to /tmp/spawn-cron-telegram-result.json
  4. After the 1h soak wait, read the result file and verify "ok":true

Test plan

  • Manual: Run SOAK_WAIT_SECONDS=120 SOAK_CRON_DELAY_SECONDS=60 bash sh/e2e/e2e.sh --soak with short timers to verify the cron fires
  • Full soak: Trigger via ?reason=soak on the QA server to run the full 1h cycle

🤖 Generated with Claude Code

AhmedTMMand others added 3 commits March 11, 2026 23:50
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM marked this pull request as ready for review March 12, 2026 07:37
@AhmedTMM
AhmedTMMforce-pushed the soak/cron-telegram-test branch from 6283424 to 830e67dCompareMarch 12, 2026 07:47

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: CHANGES REQUESTED
Commit: 830e67d

Findings

CRITICAL - sh/e2e/lib/soak.sh:247-248 — Command injection via unquoted SOAK_CRON_DELAY_SECONDS

# VULNERABLE:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' ...")# FIX: Add quotes and validate
fire_at=$(cloud_exec "${app}""date -u -d '+\"${SOAK_CRON_DELAY_SECONDS}\" seconds' ...")

Attacker-controlled SOAK_CRON_DELAY_SECONDS='3300; rm -rf /' would execute arbitrary commands.

HIGH - sh/e2e/lib/soak.sh:20-21 — Missing input validation on numeric environment variables

SOAK_WAIT_SECONDS="${SOAK_WAIT_SECONDS:-3600}"
SOAK_CRON_DELAY_SECONDS="${SOAK_CRON_DELAY_SECONDS:-3300}"

These must be validated as positive integers before use in arithmetic or command construction.

HIGH - sh/e2e/lib/soak.sh:264-274 — Command injection via TELEGRAM_TEST_CHAT_ID in openclaw cron command
The TELEGRAM_TEST_CHAT_ID variable is interpolated into a command string and could contain shell metacharacters. Must be sanitized or validated to contain only alphanumeric/dash/underscore characters.

MEDIUM - sh/e2e/lib/soak.sh:243 — Arithmetic expansion with unvalidated input

$((SOAK_CRON_DELAY_SECONDS /60))

This will fail if SOAK_CRON_DELAY_SECONDS is not a valid integer. Add validation before arithmetic operations.

LOW - sh/e2e/lib/soak.sh:285 — Race condition with /tmp/.spawn-cron-scheduled
Using a fixed filename in /tmp could conflict if multiple soak tests run on the same VM. Consider using mktemp or including the app name in the marker filename.

Required Changes

  1. Add input validation function at the top of the file:
validate_numeric_env() {
local var_name="$1"local var_value="$2"if!printf'%s'"${var_value}"| grep -qE '^[0-9]+$';then
log_err "${var_name} must be a positive integer, got: ${var_value}"return 1
fiif [ "${var_value}"-lt 1 ] || [ "${var_value}"-gt 86400 ];then
log_err "${var_name} out of range (1-86400), got: ${var_value}"return 1
fireturn 0
}
  1. Validate environment variables after line 21:
if! validate_numeric_env "SOAK_WAIT_SECONDS""${SOAK_WAIT_SECONDS}";thenexit 1;fiif! validate_numeric_env "SOAK_CRON_DELAY_SECONDS""${SOAK_CRON_DELAY_SECONDS}";thenexit 1;fi
  1. Fix command injection on line 247-248 by properly quoting:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v+${SOAK_CRON_DELAY_SECONDS}S '+%Y-%m-%dT%H:%M:%SZ'"2>&1)||true

Note: Since these are now validated as numeric-only, the injection risk is mitigated, but proper quoting is still best practice.

  1. Validate TELEGRAM_TEST_CHAT_ID format in soak_validate_telegram_env (line 40):
if!printf'%s'"${TELEGRAM_TEST_CHAT_ID}"| grep -qE '^-?[0-9]+$';then
log_err "TELEGRAM_TEST_CHAT_ID must be numeric (chat IDs are integers)"
missing=1
fi
  1. Fix race condition on line 285:
cloud_exec "${app}""touch /tmp/.spawn-cron-scheduled-${app}"2>/dev/null ||true

Tests

  • bash -n: PASS
  • curl|bash: N/A (not a standalone installer)
  • macOS compat: OK (uses bash 3.x compatible patterns)

-- security/pr-reviewer

AhmedTMMand others added 2 commits March 12, 2026 00:51
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 40fe98f

Summary

All CRITICAL security issues from the prior review (commit 830e67d) have been resolved. The PR now includes comprehensive input validation that prevents command injection attacks.

Fixed Issues

  • CRITICAL → FIXED (Lines 32-48) — Added validate_positive_int() function with regex validation for SOAK_WAIT_SECONDS and SOAK_CRON_DELAY_SECONDS. Range check (1-86400) prevents extreme values. Validation happens before any command/arithmetic use.
  • CRITICAL → FIXED (Lines 66-68) — Added regex validation for TELEGRAM_TEST_CHAT_ID (pattern: ^-?[0-9]+$). Prevents injection via chat_id parameter in curl commands.
  • LOW (Lines 273-274, 311) — app parameter interpolated into commands without local validation. Mitigation: parameter comes from make_app_name() which should sanitize. Risk is LOW (requires attacker control of provisioning).

Tests

  • bash -n: PASS (no syntax errors)
  • bun test: N/A (no TypeScript changes)
  • curl|bash: OK (no relative paths, self-contained functions)
  • macOS compat: OK (no echo -e, source <(...), ((var++)), or set -u)

Security Properties

✓ Input validation for all user-controlled numeric parameters
✓ Regex-based validation prevents injection via special characters
✓ Base64 encoding used for sensitive tokens
✓ No new security issues introduced


-- security/pr-reviewer

@louisgv
louisgv merged commit 5b5e7d4 into OpenRouterLabs:mainMar 12, 2026
5 checks passed
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 12, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM deleted the soak/cron-telegram-test branch April 7, 2026 00:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AhmedTMM@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

test: add cron-triggered Telegram reminder to soak test - #2519

Merged
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test
Mar 12, 2026
Merged

test: add cron-triggered Telegram reminder to soak test#2519
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test

Conversation

@AhmedTMM

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a cron reminder test to the Telegram soak test that verifies OpenClaw can stay alive and execute scheduled tasks on the VM
  • Installs a one-shot cron job (~55 min delay) before the 1h soak wait that sends a Telegram message, then verifies the send succeeded after the wait
  • Moves Telegram config injection before the soak wait so the cron has the bot token immediately
  • Soak test now runs 4 tests: getMe, sendMessage, getWebhookInfo, cron-fired reminder

How it works

  1. After provisioning + verification, inject Telegram bot token into OpenClaw config
  2. Install a cron script on the VM that sleeps 55 min then sends a Telegram message with a unique marker
  3. Script writes the Telegram API response to /tmp/spawn-cron-telegram-result.json
  4. After the 1h soak wait, read the result file and verify "ok":true

Test plan

  • Manual: Run SOAK_WAIT_SECONDS=120 SOAK_CRON_DELAY_SECONDS=60 bash sh/e2e/e2e.sh --soak with short timers to verify the cron fires
  • Full soak: Trigger via ?reason=soak on the QA server to run the full 1h cycle

🤖 Generated with Claude Code

AhmedTMMand others added 3 commits March 11, 2026 23:50
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM marked this pull request as ready for review March 12, 2026 07:37
@AhmedTMM
AhmedTMMforce-pushed the soak/cron-telegram-test branch from 6283424 to 830e67dCompareMarch 12, 2026 07:47

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: CHANGES REQUESTED
Commit: 830e67d

Findings

CRITICAL - sh/e2e/lib/soak.sh:247-248 — Command injection via unquoted SOAK_CRON_DELAY_SECONDS

# VULNERABLE:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' ...")# FIX: Add quotes and validate
fire_at=$(cloud_exec "${app}""date -u -d '+\"${SOAK_CRON_DELAY_SECONDS}\" seconds' ...")

Attacker-controlled SOAK_CRON_DELAY_SECONDS='3300; rm -rf /' would execute arbitrary commands.

HIGH - sh/e2e/lib/soak.sh:20-21 — Missing input validation on numeric environment variables

SOAK_WAIT_SECONDS="${SOAK_WAIT_SECONDS:-3600}"
SOAK_CRON_DELAY_SECONDS="${SOAK_CRON_DELAY_SECONDS:-3300}"

These must be validated as positive integers before use in arithmetic or command construction.

HIGH - sh/e2e/lib/soak.sh:264-274 — Command injection via TELEGRAM_TEST_CHAT_ID in openclaw cron command
The TELEGRAM_TEST_CHAT_ID variable is interpolated into a command string and could contain shell metacharacters. Must be sanitized or validated to contain only alphanumeric/dash/underscore characters.

MEDIUM - sh/e2e/lib/soak.sh:243 — Arithmetic expansion with unvalidated input

$((SOAK_CRON_DELAY_SECONDS /60))

This will fail if SOAK_CRON_DELAY_SECONDS is not a valid integer. Add validation before arithmetic operations.

LOW - sh/e2e/lib/soak.sh:285 — Race condition with /tmp/.spawn-cron-scheduled
Using a fixed filename in /tmp could conflict if multiple soak tests run on the same VM. Consider using mktemp or including the app name in the marker filename.

Required Changes

  1. Add input validation function at the top of the file:
validate_numeric_env() {
local var_name="$1"local var_value="$2"if!printf'%s'"${var_value}"| grep -qE '^[0-9]+$';then
log_err "${var_name} must be a positive integer, got: ${var_value}"return 1
fiif [ "${var_value}"-lt 1 ] || [ "${var_value}"-gt 86400 ];then
log_err "${var_name} out of range (1-86400), got: ${var_value}"return 1
fireturn 0
}
  1. Validate environment variables after line 21:
if! validate_numeric_env "SOAK_WAIT_SECONDS""${SOAK_WAIT_SECONDS}";thenexit 1;fiif! validate_numeric_env "SOAK_CRON_DELAY_SECONDS""${SOAK_CRON_DELAY_SECONDS}";thenexit 1;fi
  1. Fix command injection on line 247-248 by properly quoting:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v+${SOAK_CRON_DELAY_SECONDS}S '+%Y-%m-%dT%H:%M:%SZ'"2>&1)||true

Note: Since these are now validated as numeric-only, the injection risk is mitigated, but proper quoting is still best practice.

  1. Validate TELEGRAM_TEST_CHAT_ID format in soak_validate_telegram_env (line 40):
if!printf'%s'"${TELEGRAM_TEST_CHAT_ID}"| grep -qE '^-?[0-9]+$';then
log_err "TELEGRAM_TEST_CHAT_ID must be numeric (chat IDs are integers)"
missing=1
fi
  1. Fix race condition on line 285:
cloud_exec "${app}""touch /tmp/.spawn-cron-scheduled-${app}"2>/dev/null ||true

Tests

  • bash -n: PASS
  • curl|bash: N/A (not a standalone installer)
  • macOS compat: OK (uses bash 3.x compatible patterns)

-- security/pr-reviewer

AhmedTMMand others added 2 commits March 12, 2026 00:51
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 40fe98f

Summary

All CRITICAL security issues from the prior review (commit 830e67d) have been resolved. The PR now includes comprehensive input validation that prevents command injection attacks.

Fixed Issues

  • CRITICAL → FIXED (Lines 32-48) — Added validate_positive_int() function with regex validation for SOAK_WAIT_SECONDS and SOAK_CRON_DELAY_SECONDS. Range check (1-86400) prevents extreme values. Validation happens before any command/arithmetic use.
  • CRITICAL → FIXED (Lines 66-68) — Added regex validation for TELEGRAM_TEST_CHAT_ID (pattern: ^-?[0-9]+$). Prevents injection via chat_id parameter in curl commands.
  • LOW (Lines 273-274, 311) — app parameter interpolated into commands without local validation. Mitigation: parameter comes from make_app_name() which should sanitize. Risk is LOW (requires attacker control of provisioning).

Tests

  • bash -n: PASS (no syntax errors)
  • bun test: N/A (no TypeScript changes)
  • curl|bash: OK (no relative paths, self-contained functions)
  • macOS compat: OK (no echo -e, source <(...), ((var++)), or set -u)

Security Properties

✓ Input validation for all user-controlled numeric parameters
✓ Regex-based validation prevents injection via special characters
✓ Base64 encoding used for sensitive tokens
✓ No new security issues introduced


-- security/pr-reviewer

@louisgv
louisgv merged commit 5b5e7d4 into OpenRouterLabs:mainMar 12, 2026
5 checks passed
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 12, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM deleted the soak/cron-telegram-test branch April 7, 2026 00:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AhmedTMM@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test: add cron-triggered Telegram reminder to soak test - #2519

Merged
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test
Mar 12, 2026
Merged

test: add cron-triggered Telegram reminder to soak test#2519
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test

Conversation

@AhmedTMM

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a cron reminder test to the Telegram soak test that verifies OpenClaw can stay alive and execute scheduled tasks on the VM
  • Installs a one-shot cron job (~55 min delay) before the 1h soak wait that sends a Telegram message, then verifies the send succeeded after the wait
  • Moves Telegram config injection before the soak wait so the cron has the bot token immediately
  • Soak test now runs 4 tests: getMe, sendMessage, getWebhookInfo, cron-fired reminder

How it works

  1. After provisioning + verification, inject Telegram bot token into OpenClaw config
  2. Install a cron script on the VM that sleeps 55 min then sends a Telegram message with a unique marker
  3. Script writes the Telegram API response to /tmp/spawn-cron-telegram-result.json
  4. After the 1h soak wait, read the result file and verify "ok":true

Test plan

  • Manual: Run SOAK_WAIT_SECONDS=120 SOAK_CRON_DELAY_SECONDS=60 bash sh/e2e/e2e.sh --soak with short timers to verify the cron fires
  • Full soak: Trigger via ?reason=soak on the QA server to run the full 1h cycle

🤖 Generated with Claude Code

AhmedTMMand others added 3 commits March 11, 2026 23:50
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM marked this pull request as ready for review March 12, 2026 07:37
@AhmedTMM
AhmedTMMforce-pushed the soak/cron-telegram-test branch from 6283424 to 830e67dCompareMarch 12, 2026 07:47

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: CHANGES REQUESTED
Commit: 830e67d

Findings

CRITICAL - sh/e2e/lib/soak.sh:247-248 — Command injection via unquoted SOAK_CRON_DELAY_SECONDS

# VULNERABLE:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' ...")# FIX: Add quotes and validate
fire_at=$(cloud_exec "${app}""date -u -d '+\"${SOAK_CRON_DELAY_SECONDS}\" seconds' ...")

Attacker-controlled SOAK_CRON_DELAY_SECONDS='3300; rm -rf /' would execute arbitrary commands.

HIGH - sh/e2e/lib/soak.sh:20-21 — Missing input validation on numeric environment variables

SOAK_WAIT_SECONDS="${SOAK_WAIT_SECONDS:-3600}"
SOAK_CRON_DELAY_SECONDS="${SOAK_CRON_DELAY_SECONDS:-3300}"

These must be validated as positive integers before use in arithmetic or command construction.

HIGH - sh/e2e/lib/soak.sh:264-274 — Command injection via TELEGRAM_TEST_CHAT_ID in openclaw cron command
The TELEGRAM_TEST_CHAT_ID variable is interpolated into a command string and could contain shell metacharacters. Must be sanitized or validated to contain only alphanumeric/dash/underscore characters.

MEDIUM - sh/e2e/lib/soak.sh:243 — Arithmetic expansion with unvalidated input

$((SOAK_CRON_DELAY_SECONDS /60))

This will fail if SOAK_CRON_DELAY_SECONDS is not a valid integer. Add validation before arithmetic operations.

LOW - sh/e2e/lib/soak.sh:285 — Race condition with /tmp/.spawn-cron-scheduled
Using a fixed filename in /tmp could conflict if multiple soak tests run on the same VM. Consider using mktemp or including the app name in the marker filename.

Required Changes

  1. Add input validation function at the top of the file:
validate_numeric_env() {
local var_name="$1"local var_value="$2"if!printf'%s'"${var_value}"| grep -qE '^[0-9]+$';then
log_err "${var_name} must be a positive integer, got: ${var_value}"return 1
fiif [ "${var_value}"-lt 1 ] || [ "${var_value}"-gt 86400 ];then
log_err "${var_name} out of range (1-86400), got: ${var_value}"return 1
fireturn 0
}
  1. Validate environment variables after line 21:
if! validate_numeric_env "SOAK_WAIT_SECONDS""${SOAK_WAIT_SECONDS}";thenexit 1;fiif! validate_numeric_env "SOAK_CRON_DELAY_SECONDS""${SOAK_CRON_DELAY_SECONDS}";thenexit 1;fi
  1. Fix command injection on line 247-248 by properly quoting:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v+${SOAK_CRON_DELAY_SECONDS}S '+%Y-%m-%dT%H:%M:%SZ'"2>&1)||true

Note: Since these are now validated as numeric-only, the injection risk is mitigated, but proper quoting is still best practice.

  1. Validate TELEGRAM_TEST_CHAT_ID format in soak_validate_telegram_env (line 40):
if!printf'%s'"${TELEGRAM_TEST_CHAT_ID}"| grep -qE '^-?[0-9]+$';then
log_err "TELEGRAM_TEST_CHAT_ID must be numeric (chat IDs are integers)"
missing=1
fi
  1. Fix race condition on line 285:
cloud_exec "${app}""touch /tmp/.spawn-cron-scheduled-${app}"2>/dev/null ||true

Tests

  • bash -n: PASS
  • curl|bash: N/A (not a standalone installer)
  • macOS compat: OK (uses bash 3.x compatible patterns)

-- security/pr-reviewer

AhmedTMMand others added 2 commits March 12, 2026 00:51
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 40fe98f

Summary

All CRITICAL security issues from the prior review (commit 830e67d) have been resolved. The PR now includes comprehensive input validation that prevents command injection attacks.

Fixed Issues

  • CRITICAL → FIXED (Lines 32-48) — Added validate_positive_int() function with regex validation for SOAK_WAIT_SECONDS and SOAK_CRON_DELAY_SECONDS. Range check (1-86400) prevents extreme values. Validation happens before any command/arithmetic use.
  • CRITICAL → FIXED (Lines 66-68) — Added regex validation for TELEGRAM_TEST_CHAT_ID (pattern: ^-?[0-9]+$). Prevents injection via chat_id parameter in curl commands.
  • LOW (Lines 273-274, 311) — app parameter interpolated into commands without local validation. Mitigation: parameter comes from make_app_name() which should sanitize. Risk is LOW (requires attacker control of provisioning).

Tests

  • bash -n: PASS (no syntax errors)
  • bun test: N/A (no TypeScript changes)
  • curl|bash: OK (no relative paths, self-contained functions)
  • macOS compat: OK (no echo -e, source <(...), ((var++)), or set -u)

Security Properties

✓ Input validation for all user-controlled numeric parameters
✓ Regex-based validation prevents injection via special characters
✓ Base64 encoding used for sensitive tokens
✓ No new security issues introduced


-- security/pr-reviewer

@louisgv
louisgv merged commit 5b5e7d4 into OpenRouterLabs:mainMar 12, 2026
5 checks passed
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 12, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM deleted the soak/cron-telegram-test branch April 7, 2026 00:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AhmedTMM@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test: add cron-triggered Telegram reminder to soak test - #2519

Merged
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test
Mar 12, 2026
Merged

test: add cron-triggered Telegram reminder to soak test#2519
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test

Conversation

@AhmedTMM

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a cron reminder test to the Telegram soak test that verifies OpenClaw can stay alive and execute scheduled tasks on the VM
  • Installs a one-shot cron job (~55 min delay) before the 1h soak wait that sends a Telegram message, then verifies the send succeeded after the wait
  • Moves Telegram config injection before the soak wait so the cron has the bot token immediately
  • Soak test now runs 4 tests: getMe, sendMessage, getWebhookInfo, cron-fired reminder

How it works

  1. After provisioning + verification, inject Telegram bot token into OpenClaw config
  2. Install a cron script on the VM that sleeps 55 min then sends a Telegram message with a unique marker
  3. Script writes the Telegram API response to /tmp/spawn-cron-telegram-result.json
  4. After the 1h soak wait, read the result file and verify "ok":true

Test plan

  • Manual: Run SOAK_WAIT_SECONDS=120 SOAK_CRON_DELAY_SECONDS=60 bash sh/e2e/e2e.sh --soak with short timers to verify the cron fires
  • Full soak: Trigger via ?reason=soak on the QA server to run the full 1h cycle

🤖 Generated with Claude Code

AhmedTMMand others added 3 commits March 11, 2026 23:50
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM marked this pull request as ready for review March 12, 2026 07:37
@AhmedTMM
AhmedTMMforce-pushed the soak/cron-telegram-test branch from 6283424 to 830e67dCompareMarch 12, 2026 07:47

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: CHANGES REQUESTED
Commit: 830e67d

Findings

CRITICAL - sh/e2e/lib/soak.sh:247-248 — Command injection via unquoted SOAK_CRON_DELAY_SECONDS

# VULNERABLE:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' ...")# FIX: Add quotes and validate
fire_at=$(cloud_exec "${app}""date -u -d '+\"${SOAK_CRON_DELAY_SECONDS}\" seconds' ...")

Attacker-controlled SOAK_CRON_DELAY_SECONDS='3300; rm -rf /' would execute arbitrary commands.

HIGH - sh/e2e/lib/soak.sh:20-21 — Missing input validation on numeric environment variables

SOAK_WAIT_SECONDS="${SOAK_WAIT_SECONDS:-3600}"
SOAK_CRON_DELAY_SECONDS="${SOAK_CRON_DELAY_SECONDS:-3300}"

These must be validated as positive integers before use in arithmetic or command construction.

HIGH - sh/e2e/lib/soak.sh:264-274 — Command injection via TELEGRAM_TEST_CHAT_ID in openclaw cron command
The TELEGRAM_TEST_CHAT_ID variable is interpolated into a command string and could contain shell metacharacters. Must be sanitized or validated to contain only alphanumeric/dash/underscore characters.

MEDIUM - sh/e2e/lib/soak.sh:243 — Arithmetic expansion with unvalidated input

$((SOAK_CRON_DELAY_SECONDS /60))

This will fail if SOAK_CRON_DELAY_SECONDS is not a valid integer. Add validation before arithmetic operations.

LOW - sh/e2e/lib/soak.sh:285 — Race condition with /tmp/.spawn-cron-scheduled
Using a fixed filename in /tmp could conflict if multiple soak tests run on the same VM. Consider using mktemp or including the app name in the marker filename.

Required Changes

  1. Add input validation function at the top of the file:
validate_numeric_env() {
local var_name="$1"local var_value="$2"if!printf'%s'"${var_value}"| grep -qE '^[0-9]+$';then
log_err "${var_name} must be a positive integer, got: ${var_value}"return 1
fiif [ "${var_value}"-lt 1 ] || [ "${var_value}"-gt 86400 ];then
log_err "${var_name} out of range (1-86400), got: ${var_value}"return 1
fireturn 0
}
  1. Validate environment variables after line 21:
if! validate_numeric_env "SOAK_WAIT_SECONDS""${SOAK_WAIT_SECONDS}";thenexit 1;fiif! validate_numeric_env "SOAK_CRON_DELAY_SECONDS""${SOAK_CRON_DELAY_SECONDS}";thenexit 1;fi
  1. Fix command injection on line 247-248 by properly quoting:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v+${SOAK_CRON_DELAY_SECONDS}S '+%Y-%m-%dT%H:%M:%SZ'"2>&1)||true

Note: Since these are now validated as numeric-only, the injection risk is mitigated, but proper quoting is still best practice.

  1. Validate TELEGRAM_TEST_CHAT_ID format in soak_validate_telegram_env (line 40):
if!printf'%s'"${TELEGRAM_TEST_CHAT_ID}"| grep -qE '^-?[0-9]+$';then
log_err "TELEGRAM_TEST_CHAT_ID must be numeric (chat IDs are integers)"
missing=1
fi
  1. Fix race condition on line 285:
cloud_exec "${app}""touch /tmp/.spawn-cron-scheduled-${app}"2>/dev/null ||true

Tests

  • bash -n: PASS
  • curl|bash: N/A (not a standalone installer)
  • macOS compat: OK (uses bash 3.x compatible patterns)

-- security/pr-reviewer

AhmedTMMand others added 2 commits March 12, 2026 00:51
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 40fe98f

Summary

All CRITICAL security issues from the prior review (commit 830e67d) have been resolved. The PR now includes comprehensive input validation that prevents command injection attacks.

Fixed Issues

  • CRITICAL → FIXED (Lines 32-48) — Added validate_positive_int() function with regex validation for SOAK_WAIT_SECONDS and SOAK_CRON_DELAY_SECONDS. Range check (1-86400) prevents extreme values. Validation happens before any command/arithmetic use.
  • CRITICAL → FIXED (Lines 66-68) — Added regex validation for TELEGRAM_TEST_CHAT_ID (pattern: ^-?[0-9]+$). Prevents injection via chat_id parameter in curl commands.
  • LOW (Lines 273-274, 311) — app parameter interpolated into commands without local validation. Mitigation: parameter comes from make_app_name() which should sanitize. Risk is LOW (requires attacker control of provisioning).

Tests

  • bash -n: PASS (no syntax errors)
  • bun test: N/A (no TypeScript changes)
  • curl|bash: OK (no relative paths, self-contained functions)
  • macOS compat: OK (no echo -e, source <(...), ((var++)), or set -u)

Security Properties

✓ Input validation for all user-controlled numeric parameters
✓ Regex-based validation prevents injection via special characters
✓ Base64 encoding used for sensitive tokens
✓ No new security issues introduced


-- security/pr-reviewer

@louisgv
louisgv merged commit 5b5e7d4 into OpenRouterLabs:mainMar 12, 2026
5 checks passed
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 12, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM deleted the soak/cron-telegram-test branch April 7, 2026 00:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AhmedTMM@louisgv
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

test: add cron-triggered Telegram reminder to soak test - #2519

Merged
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test
Mar 12, 2026
Merged

test: add cron-triggered Telegram reminder to soak test#2519
louisgv merged 5 commits into
OpenRouterLabs:mainfrom
AhmedTMM:soak/cron-telegram-test

Conversation

@AhmedTMM

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a cron reminder test to the Telegram soak test that verifies OpenClaw can stay alive and execute scheduled tasks on the VM
  • Installs a one-shot cron job (~55 min delay) before the 1h soak wait that sends a Telegram message, then verifies the send succeeded after the wait
  • Moves Telegram config injection before the soak wait so the cron has the bot token immediately
  • Soak test now runs 4 tests: getMe, sendMessage, getWebhookInfo, cron-fired reminder

How it works

  1. After provisioning + verification, inject Telegram bot token into OpenClaw config
  2. Install a cron script on the VM that sleeps 55 min then sends a Telegram message with a unique marker
  3. Script writes the Telegram API response to /tmp/spawn-cron-telegram-result.json
  4. After the 1h soak wait, read the result file and verify "ok":true

Test plan

  • Manual: Run SOAK_WAIT_SECONDS=120 SOAK_CRON_DELAY_SECONDS=60 bash sh/e2e/e2e.sh --soak with short timers to verify the cron fires
  • Full soak: Trigger via ?reason=soak on the QA server to run the full 1h cycle

🤖 Generated with Claude Code

AhmedTMMand others added 3 commits March 11, 2026 23:50
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM marked this pull request as ready for review March 12, 2026 07:37
@AhmedTMM
AhmedTMMforce-pushed the soak/cron-telegram-test branch from 6283424 to 830e67dCompareMarch 12, 2026 07:47

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: CHANGES REQUESTED
Commit: 830e67d

Findings

CRITICAL - sh/e2e/lib/soak.sh:247-248 — Command injection via unquoted SOAK_CRON_DELAY_SECONDS

# VULNERABLE:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' ...")# FIX: Add quotes and validate
fire_at=$(cloud_exec "${app}""date -u -d '+\"${SOAK_CRON_DELAY_SECONDS}\" seconds' ...")

Attacker-controlled SOAK_CRON_DELAY_SECONDS='3300; rm -rf /' would execute arbitrary commands.

HIGH - sh/e2e/lib/soak.sh:20-21 — Missing input validation on numeric environment variables

SOAK_WAIT_SECONDS="${SOAK_WAIT_SECONDS:-3600}"
SOAK_CRON_DELAY_SECONDS="${SOAK_CRON_DELAY_SECONDS:-3300}"

These must be validated as positive integers before use in arithmetic or command construction.

HIGH - sh/e2e/lib/soak.sh:264-274 — Command injection via TELEGRAM_TEST_CHAT_ID in openclaw cron command
The TELEGRAM_TEST_CHAT_ID variable is interpolated into a command string and could contain shell metacharacters. Must be sanitized or validated to contain only alphanumeric/dash/underscore characters.

MEDIUM - sh/e2e/lib/soak.sh:243 — Arithmetic expansion with unvalidated input

$((SOAK_CRON_DELAY_SECONDS /60))

This will fail if SOAK_CRON_DELAY_SECONDS is not a valid integer. Add validation before arithmetic operations.

LOW - sh/e2e/lib/soak.sh:285 — Race condition with /tmp/.spawn-cron-scheduled
Using a fixed filename in /tmp could conflict if multiple soak tests run on the same VM. Consider using mktemp or including the app name in the marker filename.

Required Changes

  1. Add input validation function at the top of the file:
validate_numeric_env() {
local var_name="$1"local var_value="$2"if!printf'%s'"${var_value}"| grep -qE '^[0-9]+$';then
log_err "${var_name} must be a positive integer, got: ${var_value}"return 1
fiif [ "${var_value}"-lt 1 ] || [ "${var_value}"-gt 86400 ];then
log_err "${var_name} out of range (1-86400), got: ${var_value}"return 1
fireturn 0
}
  1. Validate environment variables after line 21:
if! validate_numeric_env "SOAK_WAIT_SECONDS""${SOAK_WAIT_SECONDS}";thenexit 1;fiif! validate_numeric_env "SOAK_CRON_DELAY_SECONDS""${SOAK_CRON_DELAY_SECONDS}";thenexit 1;fi
  1. Fix command injection on line 247-248 by properly quoting:
fire_at=$(cloud_exec "${app}""date -u -d '+${SOAK_CRON_DELAY_SECONDS} seconds' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v+${SOAK_CRON_DELAY_SECONDS}S '+%Y-%m-%dT%H:%M:%SZ'"2>&1)||true

Note: Since these are now validated as numeric-only, the injection risk is mitigated, but proper quoting is still best practice.

  1. Validate TELEGRAM_TEST_CHAT_ID format in soak_validate_telegram_env (line 40):
if!printf'%s'"${TELEGRAM_TEST_CHAT_ID}"| grep -qE '^-?[0-9]+$';then
log_err "TELEGRAM_TEST_CHAT_ID must be numeric (chat IDs are integers)"
missing=1
fi
  1. Fix race condition on line 285:
cloud_exec "${app}""touch /tmp/.spawn-cron-scheduled-${app}"2>/dev/null ||true

Tests

  • bash -n: PASS
  • curl|bash: N/A (not a standalone installer)
  • macOS compat: OK (uses bash 3.x compatible patterns)

-- security/pr-reviewer

AhmedTMMand others added 2 commits March 12, 2026 00:51
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@louisgvlouisgv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 40fe98f

Summary

All CRITICAL security issues from the prior review (commit 830e67d) have been resolved. The PR now includes comprehensive input validation that prevents command injection attacks.

Fixed Issues

  • CRITICAL → FIXED (Lines 32-48) — Added validate_positive_int() function with regex validation for SOAK_WAIT_SECONDS and SOAK_CRON_DELAY_SECONDS. Range check (1-86400) prevents extreme values. Validation happens before any command/arithmetic use.
  • CRITICAL → FIXED (Lines 66-68) — Added regex validation for TELEGRAM_TEST_CHAT_ID (pattern: ^-?[0-9]+$). Prevents injection via chat_id parameter in curl commands.
  • LOW (Lines 273-274, 311) — app parameter interpolated into commands without local validation. Mitigation: parameter comes from make_app_name() which should sanitize. Risk is LOW (requires attacker control of provisioning).

Tests

  • bash -n: PASS (no syntax errors)
  • bun test: N/A (no TypeScript changes)
  • curl|bash: OK (no relative paths, self-contained functions)
  • macOS compat: OK (no echo -e, source <(...), ((var++)), or set -u)

Security Properties

✓ Input validation for all user-controlled numeric parameters
✓ Regex-based validation prevents injection via special characters
✓ Base64 encoding used for sensitive tokens
✓ No new security issues introduced


-- security/pr-reviewer

@louisgv
louisgv merged commit 5b5e7d4 into OpenRouterLabs:mainMar 12, 2026
5 checks passed
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 12, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AhmedTMM added a commit to AhmedTMM/spawn that referenced this pull request Mar 13, 2026
…bs#2519)
* test: add cron-triggered Telegram reminder to soak test
Tests OpenClaw's ability to stay alive and execute scheduled tasks.
Installs a one-shot cron on the VM before the 1h soak wait that sends
a Telegram message at ~55 min, then verifies the message was sent
after the wait completes. Also moves Telegram config injection before
the soak wait so the cron can use the bot token immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: use OpenClaw's cron scheduler instead of system crontab
Replaces the raw system cron approach with OpenClaw's built-in cron
scheduler (`openclaw cron add`). This properly tests that OpenClaw's
gateway stays alive after 1 hour and can execute scheduled tasks.
The test now:
1. Injects Telegram config + schedules an OpenClaw cron job (--at +55min)
2. Waits 1 hour (soak)
3. Verifies the job fired via `openclaw cron runs` and `openclaw cron list`
Uses --delete-after-run for one-shot semantics. Verification checks both
the run history and the auto-deletion as proof of execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify cron message on Telegram side via forwardMessage
Instead of trusting OpenClaw's self-reported cron status, we now verify
the message actually exists in the Telegram chat:
1. Extract message_id from OpenClaw's cron execution logs (tries
`openclaw cron runs`, then ~/.openclaw/cron/ directory)
2. Call Telegram's forwardMessage API with that message_id
3. If Telegram can forward it → message EXISTS in the chat (proof
from Telegram itself, not OpenClaw)
This catches cases where OpenClaw reports success but the message
never actually reached Telegram.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address security review findings in soak test
- Add validate_positive_int() and validate SOAK_WAIT_SECONDS +
SOAK_CRON_DELAY_SECONDS at startup (prevents command injection via
crafted env vars)
- Validate TELEGRAM_TEST_CHAT_ID is numeric in soak_validate_telegram_env
- Use per-app marker file /tmp/.spawn-cron-scheduled-${app} to avoid
race conditions when multiple soak tests run on the same VM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@AhmedTMM
AhmedTMM deleted the soak/cron-telegram-test branch April 7, 2026 00:42
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AhmedTMM@louisgv