diff --git a/CHANGELOG.md b/CHANGELOG.md index d48ad9efea0..d9ba36fa3d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,6 +93,7 @@ Docs: https://docs.openclaw.ai - ACP/Harness thread spawn routing: force ACP harness thread creation through `sessions_spawn` (`runtime: "acp"`, `thread: true`) and explicitly forbid `message action=thread-create` for ACP harness requests, avoiding misrouted `Unknown channel` errors. (#30957) Thanks @dutifulbob. - Docs/ACP permissions: document the correct `permissionMode` default (`approve-reads`) and clarify non-interactive permission failure behavior/troubleshooting guidance. (#31044) Thanks @barronlroth. +- Security/Logging utility hardening: remove `eval`-based command execution from `scripts/clawlog.sh`, switch to argv-safe command construction, and escape predicate literals for user-supplied search/category filters to block local command/predicate injection paths. - Security/Inbound metadata stripping: tighten sentinel matching and JSON-fence validation for inbound metadata stripping so user-authored lookalike lines no longer trigger unintended metadata removal. - Channels/Command parsing parity: align command-body parsing fields with channel command-gating text for Slack, Signal, Microsoft Teams, Mattermost, and BlueBubbles to avoid mention-strip mismatches and inconsistent command detection. - CLI/Startup (Raspberry Pi + small hosts): speed up startup by avoiding unnecessary plugin preload on fast routes, adding root `--version` fast-path bootstrap bypass, parallelizing status JSON/non-JSON scans where safe, and enabling Node compile cache at startup with env override compatibility (`NODE_COMPILE_CACHE`, `NODE_DISABLE_COMPILE_CACHE`). (#5871) Thanks @BookCatKid and @vincentkoc for raising startup reports, and @lupuletic for related startup work in #27973. diff --git a/scripts/clawlog.sh b/scripts/clawlog.sh index 06dda1085ca..b856d0eec6e 100755 --- a/scripts/clawlog.sh +++ b/scripts/clawlog.sh @@ -44,6 +44,7 @@ SERVER_ONLY=false TAIL_LINES=50 # Default number of lines to show SHOW_TAIL=true SHOW_HELP=false +STYLE_JSON=false # Function to show usage show_usage() { @@ -137,6 +138,14 @@ list_categories() { echo -e "\n${YELLOW}Note: Only categories with recent activity are shown${NC}" } +# Escape user input embedded in macOS log predicate string literals. +escape_predicate_literal() { + local value="$1" + value="${value//\\/\\\\}" + value="${value//\"/\\\"}" + printf '%s' "$value" +} + # Show help if no arguments provided if [[ $# -eq 0 ]]; then show_usage @@ -193,7 +202,7 @@ while [[ $# -gt 0 ]]; do exit 0 ;; --json) - STYLE_ARGS="--style json" + STYLE_JSON=true shift ;; --all) @@ -213,7 +222,8 @@ PREDICATE="subsystem == \"$SUBSYSTEM\"" # Add category filter if specified if [[ -n "$CATEGORY" ]]; then - PREDICATE="$PREDICATE AND category == \"$CATEGORY\"" + ESCAPED_CATEGORY=$(escape_predicate_literal "$CATEGORY") + PREDICATE="$PREDICATE AND category == \"$ESCAPED_CATEGORY\"" fi # Add error filter if specified @@ -223,29 +233,31 @@ fi # Add search filter if specified if [[ -n "$SEARCH_TEXT" ]]; then - PREDICATE="$PREDICATE AND eventMessage CONTAINS[c] \"$SEARCH_TEXT\"" + ESCAPED_SEARCH_TEXT=$(escape_predicate_literal "$SEARCH_TEXT") + PREDICATE="$PREDICATE AND eventMessage CONTAINS[c] \"$ESCAPED_SEARCH_TEXT\"" fi -# Build the command - always use sudo with --info to show private data +# Build the command as argv array to avoid shell eval injection +LOG_CMD=(sudo log) if [[ "$STREAM_MODE" == true ]]; then # Streaming mode - CMD="sudo log stream --predicate '$PREDICATE' --level $LOG_LEVEL --info" + LOG_CMD+=(stream --predicate "$PREDICATE" --level "$LOG_LEVEL" --info) echo -e "${GREEN}Streaming VibeTunnel logs continuously...${NC}" echo -e "${YELLOW}Press Ctrl+C to stop${NC}\n" else # Show mode - CMD="sudo log show --predicate '$PREDICATE'" + LOG_CMD+=(show --predicate "$PREDICATE") # Add log level for show command if [[ "$LOG_LEVEL" == "debug" ]]; then - CMD="$CMD --debug" + LOG_CMD+=(--debug) else - CMD="$CMD --info" + LOG_CMD+=(--info) fi # Add time range - CMD="$CMD --last $TIME_RANGE" + LOG_CMD+=(--last "$TIME_RANGE") if [[ "$SHOW_TAIL" == true ]]; then echo -e "${GREEN}Showing last $TAIL_LINES log lines from the past $TIME_RANGE${NC}" @@ -267,8 +279,8 @@ else fi # Add style arguments if specified -if [[ -n "${STYLE_ARGS:-}" ]]; then - CMD="$CMD $STYLE_ARGS" +if [[ "$STYLE_JSON" == true ]]; then + LOG_CMD+=(--style json) fi # Execute the command @@ -280,9 +292,9 @@ if [[ -n "$OUTPUT_FILE" ]]; then echo -e "${BLUE}Exporting logs to: $OUTPUT_FILE${NC}\n" if [[ "$SHOW_TAIL" == true ]] && [[ "$STREAM_MODE" == false ]]; then - eval "$CMD" 2>&1 | tail -n "$TAIL_LINES" > "$OUTPUT_FILE" + "${LOG_CMD[@]}" 2>&1 | tail -n "$TAIL_LINES" > "$OUTPUT_FILE" else - eval "$CMD" > "$OUTPUT_FILE" 2>&1 + "${LOG_CMD[@]}" > "$OUTPUT_FILE" 2>&1 fi # Check if file was created and has content @@ -301,9 +313,9 @@ else if [[ "$SHOW_TAIL" == true ]] && [[ "$STREAM_MODE" == false ]]; then # Apply tail for non-streaming mode - eval "$CMD" 2>&1 | tail -n "$TAIL_LINES" + "${LOG_CMD[@]}" 2>&1 | tail -n "$TAIL_LINES" echo -e "\n${YELLOW}Showing last $TAIL_LINES lines. Use --all or -n to see more.${NC}" else - eval "$CMD" + "${LOG_CMD[@]}" fi fi