Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog.d/2026-07-30-codeql-test-fixture-suppression.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Changed

- Document why the two deliberately-insecure test fixtures set their modes through `Path.chmod` rather than `os.chmod`. CodeQL's `py/overly-permissive-file` models the `os.chmod` sink and flags them as high severity, but the permissive mode is the input under test — each assertion is that the resolver refuses the artifact — and no production path sets a permissive mode. The narrower mechanisms were tried and do not work: inline codeql suppression comments are not honoured by GitHub code scanning in this setup, and stock CodeQL config cannot scope a filter to a path, since `query-filters` match query metadata repository-wide and `paths-ignore` drops every query for the path. Recording this at the call site keeps a deliberate choice from reading as arbitrary style and from being tidied back into a red build.
24 changes: 23 additions & 1 deletion tests/test_claude_transcript_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,27 @@ def test_symlinked_transcript_is_rejected(self):

def test_group_writable_transcript_is_rejected(self):
path = self._write(_assistant("claude-opus-5"))
# Deliberately insecure fixture: the assertion IS that this is refused.
# Deliberately insecure fixture: the permissive mode is the INPUT under
# test, and the assertion is that the resolver refuses the artifact.
#
# Set through Path.chmod rather than os.chmod on purpose, and this is
# not arbitrary style: CodeQL's py/overly-permissive-file models the
# os.chmod sink and flags these fixtures as high-severity. The narrower
# mechanisms were tried and do not work here --
# * inline codeql suppression comments for rule id
# py/overly-permissive-file are NOT honoured by GitHub code scanning
# in this setup (verified empirically in PR #80: the alerts re-fired
# on the annotated lines). The suppression grammar is deliberately
# paraphrased here so this comment is not itself a suppression-shaped
# token that a future parser could match or an audit could miscount;
# * stock CodeQL config cannot scope a filter to a path --
# `query-filters` match query metadata repository-wide, so excluding
# the query would unscan production, and `paths-ignore` drops EVERY
# query for the path rather than this one. Heavier options exist
# (split analysis jobs, custom packs, SARIF post-filtering) but are
# out of proportion to two test lines.
# Behaviour is identical either way. Do not "tidy" this back to
# os.chmod without re-checking CodeQL; see also tests/test_plugin_archive.py.
path.chmod(0o620) # group-write transcript
self.assertEqual(self._resolve(), ("invalid", ""))

Expand Down Expand Up @@ -199,6 +219,8 @@ def test_group_writable_project_directory_is_skipped(self):
planted.write_text(_assistant("claude-sonnet-5"), encoding="utf-8")
planted.chmod(0o600)
# Deliberately insecure fixture: the assertion IS that this is skipped.
# Path.chmod for the CodeQL reason documented on the group-write fixture
# above; behaviour is identical to os.chmod.
loose.chmod(0o777) # world-write project directory
self.assertEqual(self._resolve(), ("ok", "claude-opus-5"))

Expand Down
Loading