Files
insights/.semgrep/rules/security/insightsql-no-string-table-chain.py
zeekay 1b367e2b62 chore: rebase the tree onto upstream master
The tree was a debranded snapshot of upstream taken around 2026-02-20, and
upstream has moved about five months since. This replaces it with upstream
master, mechanically re-derived: bin/debrand does the rename, and the
pipeline and squashed migrations are restored from the shipped tree.

Not a merge. The previous import replaced the tree wholesale in a single
commit, so there is no shared content history to merge against. Reproducing
the rename on the new tree is what actually converges.

What survives: .hanzo/workflows, the Dockerfiles and bin/docker* entrypoints,
compose files, LLM.md, and insights/migrations. The squashed initial
migration is load-bearing — the live database records it by name, so
upstream's ~918 individual migrations cannot come back.

Nine products are dropped as unreferenced. Twenty-one more that we do not run
are kept anyway because the core app still imports them; unpicking those is a
refactor and does not belong in a rebase.

This base does not build yet, and the reasons are not in the rename:
upstream now wants Python 3.13.13 against our 3.12.12 and Django 5.2 against
our 4.2, and the dependency manifests still name upstream packages that we
republish under our own names. Those are decisions, not renames.
2026-08-01 15:44:40 -07:00

108 lines
3.7 KiB
Python

"""Fixtures for insightsql-no-string-table-chain rule.
Lines marked with the must-find annotation are expected to match the rule.
Lines marked as ok must not match. Run semgrep --test .semgrep/ locally.
"""
from insights.insightsql import ast
from insights.insightsql.context import InsightsQLContext
from insights.insightsql.database.schema.events import EVENTS_TABLE_TYPES, EventsTable
from insights.insightsql.database.schema.persons import PersonsTable
# ============================================================================
# SHOULD FIND — production code comparing AST chains to table-name strings
# ============================================================================
def bad_events_check(node: ast.JoinExpr) -> bool:
# ruleid: insightsql-no-string-table-chain
if isinstance(node.table, ast.Field) and node.table.chain == ["events"]:
return True
return False
def bad_persons_check(field: ast.Field) -> bool:
# ruleid: insightsql-no-string-table-chain
return field.chain == ["persons"]
def bad_sessions_check(field: ast.Field) -> bool:
# ruleid: insightsql-no-string-table-chain
return field.chain == ["sessions"]
def bad_groups_check(field: ast.Field) -> bool:
# ruleid: insightsql-no-string-table-chain
return field.chain == ["groups"]
def bad_logs_check(field: ast.Field) -> bool:
# ruleid: insightsql-no-string-table-chain
return field.chain == ["logs"]
def bad_qualified_check(field: ast.Field) -> bool:
# ruleid: insightsql-no-string-table-chain
return field.chain == ["insights", "events"]
def bad_ai_events_check(field: ast.Field) -> bool:
# ruleid: insightsql-no-string-table-chain
return field.chain == ["insights", "ai_events"]
def bad_reversed_operand(field: ast.Field) -> bool:
# ruleid: insightsql-no-string-table-chain
return ["events"] == field.chain
# ============================================================================
# SHOULD NOT FIND — correct patterns and unrelated chain comparisons
# ============================================================================
def good_isinstance_check(context: InsightsQLContext, field: ast.Field) -> bool:
# ok: insightsql-no-string-table-chain
if context.database is None:
return False
resolved = context.database.get_table([str(c) for c in field.chain])
return isinstance(resolved, EventsTable)
def good_events_family_check(context: InsightsQLContext, field: ast.Field) -> bool:
# ok: insightsql-no-string-table-chain
if context.database is None:
return False
resolved = context.database.get_table([str(c) for c in field.chain])
return isinstance(resolved, EVENTS_TABLE_TYPES)
def good_persons_isinstance(context: InsightsQLContext, field: ast.Field) -> bool:
# ok: insightsql-no-string-table-chain
resolved = context.database.get_table([str(c) for c in field.chain]) if context.database else None
return isinstance(resolved, PersonsTable)
def good_column_name_check(field: ast.Field) -> bool:
# Comparing a field chain to a COLUMN name (not a table name) is fine — these are
# property lookups, not table-identity checks.
# ok: insightsql-no-string-table-chain
if field.chain == ["timestamp"]:
return True
# ok: insightsql-no-string-table-chain
if field.chain == ["event"]:
return True
# ok: insightsql-no-string-table-chain
if field.chain == ["person_id"]:
return True
# ok: insightsql-no-string-table-chain
if field.chain == ["properties"]:
return True
return False
def good_multi_segment_property(field: ast.Field) -> bool:
# ok: insightsql-no-string-table-chain
return field.chain == ["events", "person_id"]