Skip to content

Warn against semicolons in categorisation rules editor - #724

Closed
AbdulGoodLooks wants to merge 2 commits into
ActivityWatch:masterfrom
AbdulGoodLooks:patch-1
Closed

Warn against semicolons in categorisation rules editor#724
AbdulGoodLooks wants to merge 2 commits into
ActivityWatch:masterfrom
AbdulGoodLooks:patch-1

Conversation

@AbdulGoodLooks

@AbdulGoodLooks AbdulGoodLooks commented Nov 11, 2025

Copy link
Copy Markdown

Workaround to attempt to prevent creating rules that break aw-server like this https://forum.activitywatch.net/t/invalid-syntax-for-value-to-assign-out-of-nowhere/4627/3


Important

Update validateRegex to flag semicolons in regex as invalid to prevent server errors.

  • Behavior:
    • Update validateRegex in validate.ts to return false if regex contains semicolons, preventing server errors.
  • Validation:
    • Semicolons in regex patterns are now flagged as invalid to avoid breaking aw-server.

This description was created by Ellipsis for 93f4484. You can customize this summary. It will automatically update as commits are pushed.

@ellipsis-dev ellipsis-dev Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Changes requested ❌

Reviewed everything up to 93f4484 in 1 minute and 31 seconds. Click for details.
  • Reviewed 15 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 1 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. src/util/validate.ts:6
  • Draft comment:
    Document the rationale further: consider adding the forum post URL in the comment so future maintainers understand why semicolons break aw-server.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the author to document the rationale further by adding a URL to a forum post. This is a request for additional documentation, which is not allowed according to the rules. The comment does not provide a specific code suggestion or ask for a test to be written, so it should be removed.

Workflow ID: wflow_E2xAh4bMlQ1LhDNM

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Comment thread src/util/validate.ts Outdated
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
@codecov

codecov Bot commented Nov 12, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 26.29%. Comparing base (c766e86) to head (3d1e04f).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/util/validate.ts 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #724      +/-   ##
==========================================
- Coverage   26.30%   26.29%   -0.02%     
==========================================
  Files          29       29              
  Lines        1684     1685       +1     
  Branches      301      302       +1     
==========================================
  Hits          443      443              
+ Misses       1219     1180      -39     
- Partials       22       62      +40     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ErikBjare

Copy link
Copy Markdown
Member

@TimeToBuildBob Investigate this, shouldn't it get escaped in the query and be supported? Does it break aw-server-python or aw-server-rust or both?

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Investigated both servers.

Short answer: semicolons should be supported and don't need to be blocked. Both servers handle them correctly when the regex is embedded as a string literal in the AQL query (which is what aw-webui does via JSON.stringify).

aw-server-python: Was broken — the old query2.py split statements on all semicolons without tracking string context. Fixed in ActivityWatch/aw-core#131 (merged 2026-02-27). The _split_query_statements() function now tracks quote state and skips semicolons inside string literals.

aw-server-rust: Never broken. The plex-based lexer in aw-query/src/lexer.rs tokenizes double-quoted strings first ("([^"]|(\\"))*" regex → Token::String), so a semicolon inside "abc;def" is consumed as part of the String token and the Token::Semi pattern never fires for it.

How aw-webui builds queries: queries.ts serializes categories via JSON.stringify(params.categories), which wraps regex values in double quotes. So a regex abc;def appears in the AQL query as "abc;def" — safely inside a quoted string. No escaping is needed on top of that.

Recommendation: This PR isn't needed. The original bug (forum post) was in an older aw-server-python before the aw-core fix. The right fix was aw-core#131, which is already merged. Blocking semicolons in the UI unnecessarily restricts valid regex patterns (e.g. alternation with ; characters in paths on some systems).

Could close this PR as not needed, or the contributor could be asked to add a test to aw-core instead verifying that semicolons in categorization rules work end-to-end.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Investigation complete — root cause found, fix in #918.

Short answer: yes, semicolons should be supported. Both servers handle them correctly — the bug is in the webui's client-side query splitter, not in aw-server-python or aw-server-rust.

What breaks: querystr_to_array() in queries.ts naively does .split(';') on the whole query string. Category rules with semicolons in their regex get embedded as JSON string literals:

events = categorize(events, [["Work", {"type":"regex","regex":"foo;bar"}]]);

A plain .split(';') shreds this at the ; inside the JSON string before the query ever reaches either server.

Both servers are fine: I checked aw-query/src/lexer.rs — the Rust lexer's string-literal rule ("([^\"]|(\\\"))*") captures the full quoted string including any ; inside it, so semicolons in string literals never become Token::Semi. The Python parser works the same way. Neither server sees the malformed query because the client breaks it first.

Fix: PR #918 replaces the naive split with a string-context-aware parser that only treats ; as a statement separator when it's outside a double-quoted string literal. 4 unit tests added including the regression case.

TimeToBuildBob added a commit to TimeToBuildBob/aw-webui that referenced this pull request Jul 25, 2026
querystr_to_array() was naively splitting on all ';' characters, which
shredded category rules whose regex contained a semicolon. For example,
a rule with regex "foo;bar" gets embedded into the query as:

  events = categorize(events, [["Work", {"type":"regex","regex":"foo;bar"}]]);

A plain .split(';') would cut this into two broken fragments before the
query ever reaches aw-server, causing a parse error on the server side.
Both aw-server-python and aw-server-rust handle semicolons correctly
inside quoted strings — the bug is purely in the client-side splitter.

The fix tracks string-literal context (double-quoted, with backslash
escape support) and only treats ';' as a statement separator when it
appears outside a string.

Also exports querystr_to_array for direct unit testing and adds 4 unit
tests covering: basic split, semicolon-in-string (the regression case),
escaped quote handling, and whitespace filtering.

Closes ActivityWatch#724 (the right fix is here, not a UI warning/block).
TimeToBuildBob added a commit to TimeToBuildBob/aw-webui that referenced this pull request Jul 25, 2026
querystr_to_array() was naively splitting on all ';' characters, which
shredded category rules whose regex contained a semicolon. For example,
a rule with regex "foo;bar" gets embedded into the query as:

  events = categorize(events, [["Work", {"type":"regex","regex":"foo;bar"}]]);

A plain .split(';') would cut this into two broken fragments before the
query ever reaches aw-server, causing a parse error on the server side.
Both aw-server-python and aw-server-rust handle semicolons correctly
inside quoted strings — the bug is purely in the client-side splitter.

The fix tracks string-literal context (double-quoted, with backslash
escape support) and only treats ';' as a statement separator when it
appears outside a string.

Also exports querystr_to_array for direct unit testing and adds 4 unit
tests covering: basic split, semicolon-in-string (the regression case),
escaped quote handling, and whitespace filtering.

Closes ActivityWatch#724 (the right fix is here, not a UI warning/block).
ErikBjare pushed a commit that referenced this pull request Jul 25, 2026
* fix(queries): don't split on semicolons inside string literals

querystr_to_array() was naively splitting on all ';' characters, which
shredded category rules whose regex contained a semicolon. For example,
a rule with regex "foo;bar" gets embedded into the query as:

  events = categorize(events, [["Work", {"type":"regex","regex":"foo;bar"}]]);

A plain .split(';') would cut this into two broken fragments before the
query ever reaches aw-server, causing a parse error on the server side.
Both aw-server-python and aw-server-rust handle semicolons correctly
inside quoted strings — the bug is purely in the client-side splitter.

The fix tracks string-literal context (double-quoted, with backslash
escape support) and only treats ';' as a statement separator when it
appears outside a string.

Also exports querystr_to_array for direct unit testing and adds 4 unit
tests covering: basic split, semicolon-in-string (the regression case),
escaped quote handling, and whitespace filtering.

Closes #724 (the right fix is here, not a UI warning/block).

* fix(lint): rename escape→inEscape to avoid shadowing global; fix prettier

- `escape` is a reserved JS global; rename to `inEscape` to silence no-shadow
- collapse two-line const assignment in test to satisfy prettier line-length rule

* fix(views): use querystr_to_array in all query-splitting call sites

Seven views were still doing a naive .split(';') on query strings before
sending them to aw-client. Category rules with semicolons in their regex
(e.g. "foo;bar") embed as JSON string literals inside the AQL query, so a
plain split shreds them before they reach the server.

Replace every .split(';').map(s => s.trim() + ';') chain (and the two
longer filter-variant chains in Timeline and Trends) with querystr_to_array,
which correctly skips semicolons inside double-quoted string literals.
Sign up for free to 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.

3 participants