
Создавайте и запрашивайте графовое представление исходного кода.
Разбирайте исходный код в запрашиваемые графы функций, классов, вызовов и семантических аннотаций для анализа безопасности.
Trailmark использует tree-sitter для языково-независимого разбора AST и rustworkx для высокопроизводительного обхода графов. Долгосрочная цель — объединить этот граф с мутационным тестированием и фазингом, управляемым покрытием, чтобы выявить пробелы между предположениями и тестовым покрытием, которые достижимы из пользовательского ввода.
Trailmark работает в три фазы: parse, index и query.```mermaid flowchart TD A["Source Files"] --> B["tree-sitter Parser"] B --> C["CodeGraph (nodes + edges)"] C --> D["rustworkx GraphStore"] D --> E["QueryEngine"] E --> F["JSON / Summary / Hotspots"]
classDef src fill:#007bff26,stroke:#007bff,color:#007bff
classDef parse fill:#28a74526,stroke:#28a745,color:#28a745
classDef data fill:#6f42c126,stroke:#6f42c1,color:#6f42c1
classDef query fill:#ffc10726,stroke:#e6a817,color:#e6a817
class A src
class B parse
class C,D data
class E,F query
### 1. Парсинг
Языковой парсер обходит директорию, анализирует каждый файл в AST tree-sitter и извлекает:
- **Узлы** — функции, методы, классы, структуры, интерфейсы, трейты, перечисления, модули, пространства имён
- **Рёбра** — вызовы, наследование, реализация, включение, импорты
- **Метаданные** — аннотации типов, цикломатическая сложность, ветвления, строки документации, типы исключений
### Поддерживаемые языки
| Язык | Расширения | Ключевые конструкции |
| --- | --- | --- |
| Python | `.py` | функции, классы, методы |
| JavaScript | `.js`, `.jsx`, `.mjs`, `.cjs` | функции, классы, стрелочные функции |
| TypeScript | `.ts`, `.tsx` | функции, классы, интерфейсы, перечисления |
| PHP | `.php` | функции, классы, интерфейсы, трейты |
| Ruby | `.rb` | методы, классы, модули |
| C | `.c`, `.h` | функции, структуры, перечисления |
| C++ | `.cpp`, `.hpp`, `.cc`, `.hh`, `.cxx`, `.hxx` | функции, классы, структуры, пространства имён |
| C# | `.cs` | методы, классы, интерфейсы, структуры, перечисления, пространства имён |
| Java | `.java` | методы, классы, интерфейсы, перечисления |
| Go | `.go` | функции, методы, структуры, интерфейсы |
| Rust | `.rs` | функции, структуры, трейты, перечисления, блоки impl |
| Solidity | `.sol` | контракты, интерфейсы, библиотеки, функции, модификаторы, структуры, перечисления |
| Cairo | `.cairo` | функции, трейты, структуры, перечисления, блоки impl, контракты StarkNet |
| Circom | `.circom` | шаблоны, функции, сигналы, компоненты |
| Haskell | `.hs` | функции, типы данных, классы типов, экземпляры |
| Erlang | `.erl` | функции, записи, поведения, модули |
| Miden Assembly | `.masm` | процедуры, точки входа, константы, вызовы |
| Swift | `.swift` | функции, классы, структуры, перечисления, протоколы, расширения |
| Objective-C | `.m`, `.mm`, `.h` | C-функции, классы, методы (именование на основе селекторов) |
| Kotlin | `.kt`, `.kts` | функции, классы, интерфейсы, классы данных, объекты, методы |
| Dart | `.dart` | функции, классы, абстрактные классы, методы, конструкторы |
| Move | `.move` | модули, функции, импорты, прямые вызовы |
| Tact | `.tact` | контракты, структуры, приёмники, функции |
| Func | `.fc`, `.func` | функции, включения, прямые вызовы |
| Sway | `.sw` | интерфейсы ABI, структуры, методы impl, функции |
| Rego | `.rego` | пакеты, импорты, правила политик, вызовы правил |
| Proto | `.proto` | сервисы, RPC, сообщения, поля, перечисления |
| Thrift | `.thrift` | сервисы, функции, структуры, поля, перечисления |
| GraphQL | `.graphql`, `.gql` | типы объектов, корневые операции, поля, перечисления |
| SQL | `.sql` | схемы, таблицы, представления, функции, процедуры |```mermaid
flowchart TD
subgraph "Per-File Parsing"
F["Source file"] --> TS["tree-sitter AST"]
TS --> EX["Extract nodes"]
TS --> EC["Extract call edges"]
TS --> EB["Count branches"]
TS --> ET["Resolve types"]
end
EX --> CG["CodeGraph"]
EC --> CG
EB --> CG
ET --> CG
classDef src fill:#007bff26,stroke:#007bff,color:#007bff
classDef parse fill:#28a74526,stroke:#28a745,color:#28a745
classDef extract fill:#ffc10726,stroke:#e6a817,color:#e6a817
classDef data fill:#6f42c126,stroke:#6f42c1,color:#6f42c1
class F src
class TS parse
class EX,EC,EB,ET extract
class CG data
Идентификаторы узлов следуют схеме module:function, module:Class или module:Class.method для однозначного поиска. Разбор директорий разрешает прямые кросс-файловые вызовы, когда существует уникальное определение; неоднозначные кросс-файловые вызовы оставляются с исходной целевой функцией по наилучшему предположению и помечаются как uncertain. Уверенность ребер помечается как certain (прямые вызовы, self.method()), inferred (доступ к атрибутам не-self объектов) или uncertain (динамическая диспетчеризация или неоднозначное разрешение).
GraphStore загружает CodeGraph в rustworkx PyDiGraph и строит двунаправленные отображения ID/индексов для быстрого обхода.
QueryEngine предоставляет высокоуровневый API для индексированного графа:
| Метод | Описание |
|---|---|
callers_of(name) | Прямые вызывающие объекты для указанного целевого объекта |
callees_of(name) | Прямые вызываемые объекты от указанного источника |
ancestors_of(name) | Все функции, которые могут транзитивно достичь целевого объекта (восходящий срез) |
reachable_from(name) | Все функции, транзитивно достижимые из источника |
paths_between(src, dst) | Все простые пути вызовов между двумя узлами |
connect_subgraphs(source, target) | Пути, соединяющие два именованных подграфа |
entrypoint_paths_to(name) | Пути от любой обнаруженной точки входа к целевому объекту |
attack_surface() | Точки входа, помеченные уровнем доверия, стоимостью актива и атрибутами парсера, если они присутствуют |
complexity_hotspots(n) | Функции с цикломатической сложностью ≥ n |
functions_that_raise(exc) | Функции, чей обнаруженный парсером список исключений включает exc |
generic_parameters(name) | Параметры универсального типа, объявленные узлом |
type_references(name) | Ссылки на типы параметров, возвращаемых значений, исключений и ограничений универсального типа |
annotate(name, kind, description, source) | Добавить семантическую аннотацию к узлу |
annotations_of(name, kind=None) | Получить аннотации для узла, опционально отфильтрованные по типу |
nodes_with_annotation(kind) | Все узлы, помеченные указанным типом аннотации |
clear_annotations(name, kind=None) | Удалить аннотации из узла |
diff_against(other) | Структурная разница графа этого движка по сравнению с другим |
preanalysis() | Запустить встроенные проходы предварительного анализа и сохранить аннотации/подграфы |
augment_sarif(path) | Объединить результаты SARIF в граф |
augment_weaudit(path) | Объединить результаты weAudit в граф |
augment_binary(path) | Объединить внешний JSON-файл графа анализа бинарного кода |
findings(kind=None) | Вернуть узлы, содержащие аннотации типа "finding" |
subgraph(name) | Вернуть узлы в именованном подграфе |
subgraph_edges(name) | Вернуть индуцированные ребра внутри именованного подграфа |
subgraph_names() | Перечислить все именованные подграфы, присутствующие в графе |
summary() | Количество узлов, количество ребер, зависимости |
to_json() | Полный экспорт графа |