Skip to content

AI-2134 Validate issue_id and --root in init_task_record.py to block path traversal#3

Open
Harukaon wants to merge 1 commit into
RachelXiaolan:mainfrom
Harukaon:linear/ai-2134-fix-init-task-record-path-validation
Open

AI-2134 Validate issue_id and --root in init_task_record.py to block path traversal#3
Harukaon wants to merge 1 commit into
RachelXiaolan:mainfrom
Harukaon:linear/ai-2134-fix-init-task-record-path-validation

Conversation

@Harukaon

Copy link
Copy Markdown

Summary

scripts/init_task_record.py previously accepted any string for the issue_id positional argument and --root flag, then composed it directly into a filesystem path with Path(...). That let:

  • ../etc/passwd → escape the tasks/ root
  • /etc/passwd → write to an absolute path
  • "" → create a stray tasks/ directory
  • whitespace / newlines → split arguments if the value were ever piped to a shell

This PR tightens the validator:

  • Requires issue_id to match a strict Linear identifier format (<TEAM_KEY>-<NUMBER>, e.g. AI-2134).
  • Rejects whitespace, path separators, and shell metacharacters (/\;&|\$><\n\r\t`) up front so the error message is clear.
  • Requires --root to be a relative path with no .. segments.
  • Belt-and-suspenders: after resolving the task dir, confirms it is still under the artifact root before creating anything.
  • Exits with code 2 on invalid input (was: stack trace, exit code 1).

Tests

tests/test_init_task_record.py — 18 unit + argv-level cases covering the happy path, lowercase normalization, path traversal, absolute paths, whitespace, missing dash, missing number, hidden .., and an end-to-end subprocess invocation that confirms bad input is rejected at the CLI layer.

python3 -m unittest tests/test_init_task_record.py -v
# Ran 18 tests in 0.131s — OK

Related

Checklist

  • Diff is minimal (only init_task_record.py, new tests/, CHANGELOG.md)
  • Backward compatible for valid Linear identifiers
  • All existing happy-path invocations still produce the same artifact layout
  • New tests pass

… traversal

scripts/init_task_record.py previously accepted any string for the
issue_id positional argument and --root flag, then composed it into
a filesystem path with Path(...). This let:

  * '../etc/passwd'        -> escape the tasks/ root
  * '/etc/passwd'          -> write to an absolute path
  * ''                     -> create a stray 'tasks/' dir
  * whitespace / newlines  -> split arguments if piped to a shell

The validator now requires a strict Linear identifier format
(<TEAM_KEY>-<NUMBER>, e.g. AI-2134), rejects whitespace, path
separators, and shell metacharacters, refuses absolute --root, and
verifies that the resolved task dir is still under the artifact root
before creating it.

Also adds tests/test_init_task_record.py (18 cases: unit-level +
argv-level smoke) and updates CHANGELOG.md.
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.

1 participant