Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
trailmark — Erstellen und Abfragen einer Graphdatenbank-Repräsentation von Quellcode | Kitploit
Tools/GitHubGitHub/trailofbits/trailmark
Statische AnalyseSchwachstellenanalyseCode-AnalyseFuzzingBinäranalyseLernen & Bildung
GitHubtrailofbits/trailmark

trailmark

Erstellen und Abfragen einer Graphdatenbank-Repräsentation von Quellcode

Repository anzeigen
4632925vor 3 TagenVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
# Trailmark

[![CI](https://github.com/trailofbits/trailmark/actions/workflows/ci.yml/badge.svg)](https://github.com/trailofbits/trailmark/actions/workflows/ci.yml)
[![Mutation Testing](https://github.com/trailofbits/trailmark/actions/workflows/mutation.yml/badge.svg)](https://github.com/trailofbits/trailmark/actions/workflows/mutation.yml)

Quellcode in abfragbare Graphen aus Funktionen, Klassen, Aufrufen und semantischen Annotationen für die Sicherheitsanalyse parsen.

Trailmark verwendet [tree-sitter](https://tree-sitter.github.io/) für sprachunabhängiges AST-Parsing und [rustworkx](https://www.rustworkx.org/) für leistungsstarke Graph-Traversierung. Die langfristige Vision besteht darin, diesen Graphen mit Mutation Testing und coverage-gesteuertem Fuzzing zu kombinieren, um Lücken zwischen Annahmen und Testabdeckung zu identifizieren, die von Benutzereingaben aus erreichbar sind.

## Funktionsweise

Trailmark arbeitet in drei Phasen: **Parsen**, **Indizieren** und **Abfragen**.

```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. Parsen

Ein sprachspezifischer Parser durchläuft das Verzeichnis, parst jede Datei in einen tree-sitter-AST und extrahiert:

- **Knoten** — Funktionen, Methoden, Klassen, Structs, Interfaces, Traits, Enums, Module, Namespaces
- **Kanten** — Aufrufe, Vererbung, Implementierung, Containment, Importe
- **Metadaten** — Typannotationen, zyklomatische Komplexität, Verzweigungen, Docstrings, Ausnahmetypen

### Unterstützte Sprachen

| Sprache | Erweiterungen | Zentrale Konstrukte |
| --- | --- | --- |
| Python | `.py` | Funktionen, Klassen, Methoden |
| JavaScript | `.js`, `.jsx`, `.mjs`, `.cjs` | Funktionen, Klassen, Arrow-Funktionen |
| TypeScript | `.ts`, `.tsx` | Funktionen, Klassen, Interfaces, Enums |
| PHP | `.php` | Funktionen, Klassen, Interfaces, Traits |
| Ruby | `.rb` | Methoden, Klassen, Module |
| C | `.c`, `.h` | Funktionen, Structs, Enums |
| C++ | `.cpp`, `.hpp`, `.cc`, `.hh`, `.cxx`, `.hxx` | Funktionen, Klassen, Structs, Namespaces |
| C# | `.cs` | Methoden, Klassen, Interfaces, Structs, Enums, Namespaces |
| Java | `.java` | Methoden, Klassen, Interfaces, Enums |
| Go | `.go` | Funktionen, Methoden, Structs, Interfaces |
| Rust | `.rs` | Funktionen, Structs, Traits, Enums, Impl-Blöcke, `verus!`-Blöcke |
| Solidity | `.sol` | Contracts, Interfaces, Libraries, Funktionen, Modifier, Structs, Enums |
| Cairo | `.cairo` | Funktionen, Traits, Structs, Enums, Impl-Blöcke, StarkNet-Contracts |
| Circom | `.circom` | Templates, Funktionen, Signale, Komponenten |
| Haskell | `.hs` | Funktionen, Datentypen, Typklassen, Instanzen |
| Erlang | `.erl` | Funktionen, Records, Behaviours, Module |
| Miden Assembly | `.masm` | Prozeduren, Entrypoints, Konstanten, Aufrufe |
| Swift | `.swift` | Funktionen, Klassen, Structs, Enums, Protokolle, Extensions |
| Objective-C | `.m`, `.mm`, `.h` | C-Funktionen, Klassen, Methoden (selektorbasierte Benennung) |
| Kotlin | `.kt`, `.kts` | Funktionen, Klassen, Interfaces, Data Classes, Objekte, Methoden |
| Dart | `.dart` | Funktionen, Klassen, abstrakte Klassen, Methoden, Konstruktoren |
| Move | `.move` | Module, Funktionen, Importe, direkte Aufrufe |
| Tact | `.tact` | Contracts, Structs, Receiver, Funktionen |
| Func | `.fc`, `.func` | Funktionen, Includes, direkte Aufrufe |
| Sway | `.sw` | ABI-Interfaces, Structs, Impl-Methoden, Funktionen |
| Rego | `.rego` | Pakete, Importe, Policy-Regeln, Regelaufrufe |
| Proto | `.proto` | Services, RPCs, Messages, Felder, Enums |
| Thrift | `.thrift` | Services, Funktionen, Structs, Felder, Enums |
| GraphQL | `.graphql`, `.gql` | Objekttypen, Root-Operationen, Felder, Enums |
| SQL | `.sql` | Schemas, Tabellen, Views, Funktionen, Prozeduren |

Der Rust-Parser extrahiert gewöhnliche `spec`- und `proof`-Funktionen mit Rümpfen
aus `verus! { ... }`-Blöcken. Die Verus-Grammatik unterstützt derzeit nur
klammerbegrenzte Blöcke; `verus!(...)` und `verus![...]` werden mit einer Warnung übersprungen.
Inline-Module behalten qualifizierte IDs (zum Beispiel `file.inner:function`), und
Methoden behalten ihren Impl- oder Trait-Eigentümer. Jeder Block wird unabhängig geparst;
Syntaxfehler erzeugen eine Warnung mit der Datei- und Blockposition.
Qualifizierte Aufrufe wie `vstd::prelude::verus!` werden ebenfalls unterstützt.
Lokale Hilfsfunktionen behalten ihre umschließende Funktion in ihren IDs (zum Beispiel
`file:outer.inner`). Aufrufe dieser Hilfsfunktionen und relative Importe wie
`use super::*` werden zu Deklarationen aufgelöst, die in der Datei vorhanden sind.
Wiederholte lokale Namen in verschiedenen Blöcken erhalten ein Byte-Offset-Suffix, um
ihre Knoten unterscheidbar zu halten, und Aufrufe respektieren den Blockbereich.
Lokale Structs, Enums, Traits und Inline-Module behalten ebenfalls die umschließende Funktion
bei: zum Beispiel `file:outer.Guard.drop` und `file:outer.local.helper`.
Ihre Rümpfe haben separate Aufrufe und Komplexität. Explizite Aufrufe bekannter lokaler
Typen und Module werden innerhalb der Datei aufgelöst. Bloße Aufrufe durchsuchen Funktions- und Modul-
bereiche; zugehörige Elemente verwenden Pfade wie `Type::method`. Punktierte Aufrufe werden
nur aufgelöst, wenn der Empfänger einen bekannten Struct oder Enum benennt. Andere Wertempfänger,
einschließlich `self.method()`, bleiben unaufgelöst. Implizite Destruktoraufrufe und Empfänger-
Typinferenz werden nicht modelliert. Diese Regeln gelten sowohl für gewöhnliches Rust als auch für
Verus-Blöcke. Das Bearbeiten von Code vor einer Deklaration mit einem Offset-Suffix ändert
ihre ID, sodass `trailmark diff` diese Deklaration als entfernt und hinzugefügt melden kann.

Trailmark expandiert keine beliebigen Makros. Literale Verus-Aufrufe innerhalb
opaker Makros oder Funktionsrümpfe werden mit einer Warnung übersprungen. Nicht aufgerufene
`macro_rules!`-Definitionen werden nicht expandiert. Funktionssignaturen ohne Rümpfe
und Aufrufe in `requires`/`ensures`-Klauseln werden nicht extrahiert.

```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
```

Knoten-IDs folgen dem Schema `module:function`, `module:Class` oder `module:Class.method` für eine eindeutige Auflösung. Die Verzeichnisanalyse löst bloße dateiübergreifende Aufrufe auf, wenn eine eindeutige Definition existiert; mehrdeutige dateiübergreifende Aufrufe bleiben bei ihrem ursprünglichen Best-Effort-Ziel und werden als `uncertain` markiert. Die Kantenkonfidenz wird als `certain` (direkte Aufrufe, `self.method()`), `inferred` (Attributzugriff auf Nicht-Self-Objekte) oder `uncertain` (dynamischer Dispatch oder mehrdeutige Auflösung) gekennzeichnet.

### 2. Index

Der `GraphStore` lädt den `CodeGraph` in einen rustworkx `PyDiGraph` und erstellt bidirektionale ID/Index-Zuordnungen für eine schnelle Traversierung.

### 3. Abfrage

Die `QueryEngine` bietet eine High-Level-API über dem indizierten Graphen:

| Methode | Beschreibung |
| --- | --- |
| `callers_of(name)` | Direkte Aufrufer des benannten Ziels |
| `callees_of(name)` | Direkte Aufgerufene der benannten Quelle |
| `ancestors_of(name)` | Jede Funktion, die das Ziel transitiv erreichen kann (aufsteigender Slice) |
| `reachable_from(name)` | Jede Funktion, die von der Quelle aus transitiv erreichbar ist |
| `paths_between(src, dst)` | Alle einfachen Aufrufpfade zwischen zwei Knoten |
| `connect_subgraphs(source, target)` | Pfade, die zwei benannte Teilgraphen verbinden |
| `entrypoint_paths_to(name)` | Pfade von jedem erkannten Einstiegspunkt zum Ziel |
| `attack_surface()` | Einstiegspunkte, gekennzeichnet mit Vertrauensstufe, Asset-Wert und Parser-Attributen, sofern vorhanden |
| `complexity_hotspots(n)` | Funktionen mit zyklomatischer Komplexität ≥ n |
| `functions_that_raise(exc)` | Funktionen, deren vom Parser erkannte Ausnahmeliste `exc` enthält |
| `generic_parameters(name)` | Vom Knoten deklarierte generische Typparameter |
| `type_references(name)` | Typreferenzen aus Parametern, Rückgabewerten, Ausnahmen und generischen Bounds |
| `annotate(name, kind, description, source)` | Fügt einem Knoten eine semantische Annotation hinzu |
| `annotations_of(name, kind=None)` | Ruft Annotationen für einen Knoten ab, optional nach Art gefiltert |
| `nodes_with_annotation(kind)` | Jeder Knoten, der mit der angegebenen Annotationsart gekennzeichnet ist |
| `clear_annotations(name, kind=None)` | Entfernt Annotationen von einem Knoten |
| `diff_against(other)` | Struktureller Diff des Graphen dieser Engine gegen einen anderen |
| `preanalysis()` | Führt die integrierten Voranalyse-Durchläufe aus und speichert Annotationen/Teilgraphen |
| `augment_sarif(path)` | Führt SARIF-Funde in den Graphen zusammen |
| `augment_weaudit(path)` | Führt weAudit-Funde in den Graphen zusammen |
| `augment_binary(path)` | Führt eine externe JSON-Datei eines Binäranalyse-Graphen zusammen |
| `findings(kind=None)` | Gibt Knoten zurück, die Fund-Annotationen tragen |
| `subgraph(name)` | Gibt die Knoten in einem benannten Teilgraphen zurück |
| `subgraph_edges(name)` | Gibt die induzierten Kanten innerhalb eines benannten Teilgraphen zurück |
| `subgraph_names()` | Listet jeden derzeit im Graphen vorhandenen benannten Teilgraphen auf |
| `summary()` | Knotenanzahl, Kantenanzahl, Abhängigkeiten |
| `to_json()` | Vollständiger Graph-Export |

### Datenmodell

```mermaid
classDiagram
    class CodeGraph {
        language: str
        root_path: str
        nodes: dict[str, CodeUnit]
        edges: list[CodeEdge]
        annotations: dict[str, list[Annotation]]
        entrypoints: dict[str, EntrypointTag]
        dependencies: list[str]
        add_annotation(node_id, annotation)
        clear_annotations(node_id, kind=None)
        merge(other)
    }

    class CodeUnit {
        id: str
        name: str
        kind: NodeKind
        location: SourceLocation
        parameters: tuple[Parameter]
        return_type: TypeRef
        exception_types: tuple[TypeRef]
        cyclomatic_complexity: int
        branches: tuple[BranchInfo]
        docstring: str
    }

    class CodeEdge {
        source_id: str
        target_id: str
        kind: EdgeKind
        confidence: EdgeConfidence
    }

    class Annotation {
        kind: AnnotationKind
        description: str
        source: str
    }

    class EntrypointTag {
        kind: EntrypointKind
        trust_level: TrustLevel
        description: str
        asset_value: AssetValue
    }

    CodeGraph "1" *-- "*" CodeUnit
    CodeGraph "1" *-- "*" CodeEdge
    CodeGraph "1" *-- "*" Annotation
    CodeGraph "1" *-- "*" EntrypointTag
```

**Knotenarten:** `function`, `method`, `class`, `module`, `struct`, `interface`, `trait`, `enum`, `namespace`, `contract`, `library`, `template`, `proxy`

**Knotenursprünge:** `source`, `proxy`, `binary`, `synthetic`

**Kantenarten:** `calls`, `inherits`, `implements`, `contains`, `imports`, `resolves_to`, `type_uses`, `specializes`, `corresponds_to`

**Kantenkonfidenz:** `certain`, `inferred`, `uncertain`

Nicht aufgelöste Aufrufe werden als Proxy-Knoten wie
`proxy.unresolved:<raw-symbol>` materialisiert, sodass Traversierungsergebnisse zeigen können, wo die Quellcodeanalyse die Auflösung verloren hat, anstatt diese Kante stillschweigend zu verwerfen. Verzeichnis-Parses, einschließlich einsprachiger Parses, wenden ebenfalls Repository-Links an und materialisieren `TYPE_USES`-Kanten. Die Binäranalyse-Unterstützung importiert externe JSON-Aufrufgraphen; Trailmark disassembliert ausführbare Dateien nicht selbst.

### Beispielgraph

Gegeben dieser Python-Code:

```python
class Auth:
    def verify(self, token: str) -> bool:
        return self._check_sig(token)

    def _check_sig(self, token: str) -> bool:
        ...

def handle_request(req: Request) -> Response:
    auth = Auth()
    if auth.verify(req.token):
        return process(req)
    return deny()
```

Trailmark erzeugt einen Graphen wie:

```mermaid
graph TD
    HR["handle_request"] -->|calls| AV["Auth.verify"]
    HR -->|calls| P["process"]
    HR -->|calls| D["deny"]
    AV -->|calls| CS["Auth._check_sig"]
    A["Auth"] -->|contains| AV
    A -->|contains| CS

    classDef fn fill:#007bff26,stroke:#007bff,color:#007bff
    classDef cls fill:#6f42c126,stroke:#6f42c1,color:#6f42c1

    class HR,P,D fn
    class A,AV,CS cls
```

## Installation

Die folgenden Beispiele beziehen sich auf den aktuellen Entwicklungszweig. Für das neueste
veröffentlichte Paket installieren Sie von PyPI. Für den hier beschriebenen
genauen Funktionsumfang installieren Sie aus einem Checkout und führen Befehle über `uv run` aus.

```bash
# Latest published release
uv pip install trailmark

# Current checkout / development branch
uv sync --all-groups
```

Erfordert Python &ge; 3.12.

Trailmark benötigt `tree-sitter-language-pack` 1.22.1 oder neuer für die meisten Grammatiken.
Root-eigene Grammatik-Caches werden unterstützt, sofern sie nicht für Gruppe oder andere beschreibbar sind.
Aktuelle Releases verwenden den Zertifikatsspeicher der Plattform für Grammatik-Downloads. In
Umgebungen mit TLS-Inspektion oder Offline-Umgebungen füllen Sie den Paket-Cache vorab mit
`python -c "import tree_sitter_language_pack as p; p.download_all()"` auf einer
passenden Plattform und kopieren Sie anschließend das resultierende `tree-sitter-language-pack`-Cache-
Verzeichnis auf die Zielmaschine. `HTTPS_PROXY` wird ebenfalls berücksichtigt. Die SQL-Grammatik
wird als Wheel-Abhängigkeit `tree-sitter-sql` ausgeliefert und verwendet diesen Cache nicht.

Die mitgelieferten Grammatiken für Circom, Miden Assembly und Verus werden bei der ersten Verwendung kompiliert.
Dies erfordert einen C-Compiler (`cc`), Python-Entwicklungsheader und Schreibzugriff
auf ihre installierten Grammatikverzeichnisse. Rust-Dateien ohne Verus-Blöcke lösen keine
Kompilierung aus. Wenn die Verus-Grammatik nicht gebaut oder geladen werden kann, protokolliert Trailmark
eine Warnung, überspringt Verus-Blöcke und fährt mit dem Parsen von gewöhnlichem Rust fort.
Der Verus-Binding-Cache enthält die kompilierten Quellinhalte, die Python-ABI,
die Plattform und die Compiler-Optionen. Geänderte Eingaben wählen ein neues Binding; abgeschlossene
Builds werden atomar veröffentlicht. Compiler-Fehler enthalten den Exit-Status und
stderr in der Warnung.

Git-Checkouts behalten die Verus-Grammatikdefinition und generieren ihren C-Parser während
Builds mit Tree-sitter CLI 0.27.1. Führen Sie vor `uv sync` oder `uv build` in einem Checkout
`npm ci` mit aktivierten npm-Installationsskripten aus; Node.js wird für die Generierung benötigt.
Der generierte Parser und die Header sind gitignored. Wheels und Source-Distributionen
enthalten diese generierten Quellen, sodass die Installation veröffentlichter Pakete weder
Node.js noch die Tree-sitter CLI erfordert.
Editierbare `uv`-Installationen führen den Build-Hook erneut aus, um fehlende generierte Dateien wiederherzustellen;
unveränderte Eingaben verwenden die vorhandene Ausgabe erneut.

## Verwendung

```bash
# Report the installed version
trailmark --version     # or: trailmark -V
trailmark version       # subcommand form

# Full JSON graph (Python, the default)
trailmark analyze path/to/project

# Analyze a different language
trailmark analyze --language rust path/to/project
trailmark analyze --language javascript path/to/project

# Polyglot: auto-detect and merge every supported language found in the
# tree, or pass an explicit comma-separated list.
trailmark analyze --language auto path/to/project
trailmark analyze --language python,rust,solidity path/to/project

# Summary statistics
trailmark analyze --summary path/to/project

# Complexity hotspots (threshold >= 10)
trailmark analyze --complexity 10 path/to/project

# Augment the graph with external findings (SARIF from static analyzers,
# weAudit findings from the VS Code extension). Each --sarif / --weaudit
# flag is repeatable. Add --json to print the augmented graph.
trailmark augment --sarif results.sarif path/to/project
trailmark augment --weaudit findings.json path/to/project
trailmark augment --sarif a.sarif --sarif b.sarif --json path/to/project

# List detected entrypoints (attack surface). Uses heuristic detection
# (main() functions, pyproject.toml [project.scripts]) plus an optional
# override file at .trailmark/entrypoints.toml (see below).
trailmark entrypoints path/to/project
trailmark entrypoints --json path/to/project

# Structural diff between two code graphs. Accepts directory paths or
# git refs (branches, tags, commits). Surfaces added/removed nodes,
# call-edge changes, and — most usefully — attack-surface changes.
trailmark diff before/ after/
trailmark diff --repo . main HEAD          # compare git refs
trailmark diff --json before/ after/        # machine-readable output

# Generate a Mermaid diagram from the code graph. --type is required; the
# choices are call-graph, class-hierarchy, module-deps, containment,
# complexity, and data-flow. Use --focus to scope large graphs.
trailmark diagram --target path/to/project --type call-graph
trailmark diagram -t path/to/project -T call-graph -f parse_file --depth 3
trailmark diagram -t path/to/project -T complexity --threshold 5 --direction LR
```

### Erkennung von Einstiegspunkten

Trailmark füllt `graph.entrypoints` automatisch, damit `attack_surface()`, die Taint-Propagierung und das Überschreiten von Privilegiengrenzen Daten zur Verfügung haben. Die Erkennung läuft in vier Schichten, wobei jede die vorherige überschreibt:

1. **Generische `main`-Heuristik.** Jede Funktion namens `main` in jeder Sprache. Getaggt mit `user_input` / `trusted_internal` / `low`.
2. **Framework-bewusster Scan.** Decorator-, Attribut- und Sichtbarkeitsmuster pro Sprache — siehe die Tabelle unten.
3. **`pyproject.toml [project.scripts]`.** Explizite CLI-Ziele erhalten eine höhergestufte Vertrauens-/Asset-Klassifizierung.
4. **Repo-lokale Override-Datei.** Handkuratierte Einstiegspunkte in `.trailmark/entrypoints.toml` gewinnen immer.

Framework-Abdeckung:

| Sprache | Erkannte Frameworks |
| --- | --- |
| Python | Flask, FastAPI, aiohttp, Click, Typer, Celery |
| JavaScript / TypeScript | NestJS, Next.js (App Router + Pages API), AWS Lambda |
| Java | Spring MVC / WebFlux, JAX-RS, Kafka-Listener, Servlets |
| C# | ASP.NET Core, Azure Functions |
| PHP | Symfony `#[Route]`-Attribute + Legacy-Annotationen |
| Rust | actix-web, rocket, FFI-Exporte (`#[no_mangle]`, `pub extern "C"`), async-main-Attribute |
| Solidity | `external` / `public` Sichtbarkeit |
| Cairo / StarkNet | `#[external]`, `#[view]`, `#[l1_handler]`, `#[constructor]` |
| Circom | `component main`-Deklarationen |
| Miden Assembly | `export.<name>`-Direktiven |
| Haskell | Top-Level `main ::` / `main =` |
| Erlang | Funktionen, die in `-export([...])` aufgeführt sind |
| Swift | `@main`-App-Attribut |
| Objective-C | `UIApplicationDelegate`-Lifecycle-Selektoren (z. B. `application:openURL:options:`) |
| Kotlin | Spring MVC / WebFlux-Annotationen (gemeinsam mit Java), Android-Komponenten-Lifecycle-Methoden (`onCreate`, `onReceive`, `onBind`, ...) |
| Dart | `@pragma('vm:entry-point')`-Native-Callable-Marker |
| Go | `http.HandleFunc` / `http.Handle`-Registrierungen aus der Standardbibliothek, Handler-Registrierungen im gin/chi/echo-Stil `<router>.GET/POST/...` |
| Ruby | Rails-Controller-Actions (Klassen, die von `ApplicationController` / `ActionController::*` erben), Sidekiq-Worker-`perform`-Methoden |
| C / C++ | `extern "C"`-Bindung, `__attribute__((visibility("default")))`, `__declspec(dllexport)` |

Für alles, was die Heuristiken übersehen, deklarieren Sie Einstiegspunkte explizit in `.trailmark/entrypoints.toml` im Projektstamm. Die Datei unterstützt sowohl Einzelknoten- als auch regelbasierte Einträge:

```toml
# Single-node entry
[[entrypoint]]
node = "my_module:handle_request"  # node id, or "module.path:function"
kind = "api"                       # user_input | api | database | file_system | third_party
trust = "untrusted_external"       # untrusted_external | semi_trusted_external | trusted_internal
asset_value = "high"               # high | medium | low
description = "HTTP POST /auth"

# Rule: every PHP script under public_html/ is a web-exposed entrypoint.
[[entrypoint]]
file_glob = "public_html/**/*.php"
kind = "user_input"
trust = "untrusted_external"
asset_value = "high"
description = "Web-exposed PHP script"

# Rule: any function that takes a PSR-7 request object.
[[entrypoint]]
param_type = "ServerRequestInterface"
kind = "api"
trust = "untrusted_external"
asset_value = "high"
description = "PSR-7 HTTP handler"

# Rule: functions named `handle_*`.
[[entrypoint]]
name_regex = "^handle_"
kind = "api"
trust = "untrusted_external"

# Rule: conditions compose with AND — web.py files AND name starts with handle_.
[[entrypoint]]
file_glob = "public/*.py"
name_regex = "^handle_"
kind = "api"
trust = "untrusted_external"
```

Spätere Einträge überschreiben frühere, wenn zwei Regeln denselben Knoten markieren, daher sollten allgemeine Regeln zuerst und spezifische Korrekturen danach platziert werden.

Siehe [docs/entrypoint-patterns.md](https://github.com/trailofbits/trailmark/blob/main/docs/entrypoint-patterns.md) für die vollständige Referenz, einschließlich Frameworks, die noch nicht implementiert sind (Express / Koa / Fastify, Laravel, Cobra, axum, warp, clap und andere) mit grep-fertigen Mustern, die Mitwirkende verwenden können, um neue Detektoren hinzuzufügen.

Die Solidity-Erkennung verwendet Parser-Metadaten anstelle von Signatur-Regexes. Interface-Deklarationen werden ausgeschlossen, und abgeleitete Overrides annotieren passende Basisimplementierungen mit `solidity_overridden_by`, anstatt den Basis-Entrypoint zu entfernen. Konkrete `public`- und `external`-Funktionen bleiben Entrypoints, einschließlich `view`- und `pure`-Funktionen; ihre Attribute `solidity_visibility`, `solidity_mutability` und Override werden von `attack_surface()` zurückgegeben, damit Aufrufer schreibgeschützte Exposition unterscheiden und überschriebene Basisimplementierungen filtern können. `attack_surface()` enthält parserspezifische Entrypoint-Attribute, wenn sie an den zugrunde liegenden Graphknoten angehängt sind.

### Sprachübergreifende und externe Verknüpfungen

Polyglotte Analyse führt Sprachgraphen zusammen, aber viele RPC-, FFI-, Subprozess- und Host/Contract-Beziehungen sind in der Quellsyntax nicht sichtbar. Deklarieren Sie diese deterministisch in `.trailmark/links.toml`:

```toml
[[link]]
source = "backend:submit"
target = "contract:Verifier.verify"
kind = "calls"                 # defaults to calls
confidence = "certain"         # defaults to inferred
description = "JSON-RPC eth_call"

[[link]]
source = "backend:notify"
target = "payments-webhook"
target_external = true         # required because target is unresolved
```

Referenzen können exakte Knoten-IDs oder eindeutige Namen/Suffixe sein. Mehrdeutige Referenzen,
unbekannte interne Endpunkte, ungültige Enum-Werte und fehlerhaftes TOML lösen
`ValueError` aus. Das Setzen von `source_external = true` oder `target_external = true`
erlaubt diesen unaufgelösten Endpunkt explizit und erstellt einen Proxy-Knoten. Diese Datei
ist eine stabile öffentliche Konfigurationsschnittstelle.

### Einschränkungen der Analyse

- `entrypoint_paths_to()` meldet die Erreichbarkeit im Aufrufgraphen, nicht den angreifergesteuerten
  Datenfluss. Verwenden Sie die Taint-Ergebnisse der Voranalyse als grobes separates Signal; Trailmark
  führt noch keine interprozedurale Taint-Analyse durch.
- TypeScript löst direkte Aufrufe und einfache Empfänger auf, die mit
  `new ConcreteClass()` zugewiesen wurden. Interface-Dispatch über Manifeste, berechnete Property-
 Namen, Dependency-Injection-Container und andere dynamische Mechanismen bleibt
  Best-Effort.
- Die SQL-Unterstützung ist PostgreSQL-orientiert und extrahiert Schemas, Tabellen, Views,
  Funktionen, Prozeduren sowie Routine-/View-Abhängigkeiten. Sie ist kein vollständiger
  SQL-Dialekt-Validator oder Abfrage-Semantik-Analysator.

### Programmatische API

```python
from trailmark.parse import parse_directory, parse_file
from trailmark.query.api import QueryEngine

# Parse-only API: get the raw CodeGraph without building GraphStore/QueryEngine.
graph = parse_file("path/to/file.py")
graph = parse_directory("path/to/project", language="auto")

# Single-language (default) or auto-detect + merge across all languages
engine = QueryEngine.from_directory("path/to/project")
engine = QueryEngine.from_directory("path/to/project", language="auto")
engine = QueryEngine.from_directory("path/to/project", language="python,rust")

# Direct neighbors
engine.callers_of("handle_request")
engine.callees_of("handle_request")

# Transitive slicing — who could reach this sink, or what could it reach?
engine.ancestors_of("Auth._check_sig")
engine.reachable_from("handle_request")

# Attack-surface paths from any detected entrypoint
engine.entrypoint_paths_to("Auth._check_sig")

# All call paths between two nodes
engine.paths_between("handle_request", "Auth._check_sig")

# Functions with cyclomatic complexity >= 10
engine.complexity_hotspots(10)

# What functions can raise a given exception? (uses parser-detected
# exception_types; no runtime tracing required)
engine.functions_that_raise("PermissionError")

# Add and query semantic annotations
from trailmark.models.annotations import AnnotationKind

engine.annotate(
    "handle_request",
    AnnotationKind.ASSUMPTION,
    "Caller has already authenticated the session token",
    source="llm",
)
engine.annotations_of("handle_request")
engine.nodes_with_annotation(AnnotationKind.FINDING)

# Diff against an earlier snapshot of the same codebase
before = QueryEngine.from_directory("before/")
diff = engine.diff_against(before)
# diff contains: summary_delta, nodes {added/removed/modified},
# edges {added/removed}, entrypoints {added/removed/modified}

# Run the built-in audit-oriented preanalysis passes
engine.preanalysis()
engine.findings()
engine.subgraph_names()

# Programmatic augmentation hooks for external tooling
engine.augment_sarif("results.sarif")
engine.augment_weaudit("findings.json")
```

`NodeKind.SCHEMA`, `TABLE`, `VIEW` und `PROCEDURE` sind in v0.5.0 additiv;
Konsumenten, die Enum-Werte erschöpfend abgleichen, sollten Fälle dafür hinzufügen.

## Entwicklung

```bash
# Install package and dev dependencies
npm ci
uv sync --all-groups

# Lint and format
uv run ruff check --fix
uv run ruff format

# Type check
uv run --locked ty check

# Tests
uv run pytest -q tests/

# Mutation testing with pytest-gremlins
uv run python -m tests.run_mutations --reviewed --workers=4
uv run python -m tests.mutation_gate

# Full repository mutation campaign
uv run python -m tests.run_mutations --workers=4
```

Mutationsberichte werden nach `coverage/gremlins/` geschrieben. Pull Requests mutieren die in `tests/mutation_baseline.json` genannten Rust/Verus-Dateien und prüfen dort neue und geänderte Funktionen. Vollständige Repository-Kampagnen laufen bei Pushes auf main und über den manuellen Auslöser des Mutations-Workflows. Unveränderte Legacy-Funktionen werden anhand von Quell-Hashes identifiziert und gelangen automatisch in das Gate, sobald sie bearbeitet werden. Das Gate weist nicht überprüfte Survivors, fehlende Tests/Ergebnisse, Fehler und Timeouts zurück. Ausnahmen erfordern eine Begründung und einen Fingerprint der Funktion und der Mutation; eine Änderung dieser Funktion erfordert eine erneute Überprüfung ihrer Ausnahmen.

Der Runner pinnt pytest-gremlins 1.9.0 fest und verwendet echte pytest-Subprozesse für jeden Mutanten, einschließlich Fixtures und parametrisierter Tests. Jeder Mutant behält die vollständige ausgewählte Testsuite bei: Komponenten-Unit-Tests laufen zuerst, gefolgt von den übrigen Tests, wobei beim ersten Fehler abgebrochen wird. Mutanten gemeinsamer Helper behalten Tests aus jeder Sprache bei. Tests verbleiben in ihren bestehenden Dateien; `tests/mutation_order.py` definiert die Reihenfolge, und unbekannte Komponenten behalten die Sammelreihenfolge bei. Der Runner überspringt den redundanten Coverage-Pre-Scan, prüft die saubere Baseline und jede unterschiedliche instrumentierte Testreihenfolge und bewahrt Paketmetadaten sowie exakte Parameter-IDs beim Laden mutierten Codes. Diese Kompatibilitätsmaßnahmen adressieren Probleme mit dem Upstream-Runner und der Auswahl; ihre Kontrolltests müssen bestehen, bevor das Plugin aktualisiert wird.
Snapshot-Aktualisierungen (`TRAILMARK_UPDATE_SNAPSHOTS=1`) sind während CI- und Mutationsläufen deaktiviert. Um eine lokale Kampagne zu fokussieren, übergeben Sie `--targets` mit kommagetrennten Quellpfaden, gefolgt von den relevanten Testdateien. `--workers=4` aktiviert bereits die parallele Ausführung. Verwenden Sie `--test-order=collection`, um mit der ursprünglichen Reihenfolge von pytest zu vergleichen.

## Lizenz

Apache-2.0
Tool herunterladen