
بناء والاستعلام عن تمثيل قاعدة بيانات رسومية لشفرة المصدر
# Trailmark
[](https://github.com/trailofbits/trailmark/actions/workflows/ci.yml)
[](https://github.com/trailofbits/trailmark/actions/workflows/mutation.yml)
حلّل الشيفرة المصدرية إلى رسوم بيانية قابلة للاستعلام تتضمّن الدوال والأصناف والاستدعاءات والتعليقات الدلالية لأغراض تحليل الأمان.
يستخدم Trailmark مكتبة [tree-sitter](https://tree-sitter.github.io/) لتحليل شجرة التركيب النحوي (AST) بشكل مستقل عن اللغة، ومكتبة [rustworkx](https://www.rustworkx.org/) لاجتياز الرسوم البيانية عالي الأداء. تتمثل الرؤية طويلة المدى في دمج هذا الرسم البياني مع اختبار الطفرات والاختبار التوجيهي القائم على التغطية (coverage-guided fuzzing) لتحديد الفجوات بين الافتراضات وتغطية الاختبارات التي يمكن الوصول إليها من مدخلات المستخدم.
## كيف يعمل
يعمل Trailmark على ثلاث مراحل: **التحليل**، و**الفهرسة**، و**الاستعلام**.
```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، وكتل `verus!` |
| 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` | الخدمات، وRPCs، والرسائل، والحقول، والتعدادات |
| Thrift | `.thrift` | الخدمات، والدوال، والبنى، والحقول، والتعدادات |
| GraphQL | `.graphql`، `.gql` | أنواع الكائنات، والعمليات الجذرية، والحقول، والتعدادات |
| SQL | `.sql` | المخططات، والجداول، وطرق العرض، والدوال، والإجراءات |
محلل Rust يستخرج الدوال العادية و`spec` و`proof` مع أجسامها
من كتل `verus! { ... }`. تدعم قواعد Verus حاليًا الكتل المحددة
بأقواس معقوفة فقط؛ يتم تخطي `verus!(...)` و`verus![...]` مع تحذير.
تحتفظ الوحدات المضمّنة بالمعرّفات المؤهلة (على سبيل المثال، `file.inner:function`)،
وتحتفظ الطرق بمالك impl أو trait الخاص بها. يتم تحليل كل كتلة بشكل مستقل؛
تنتج أخطاء الصياغة تحذيرًا مع موقع الملف والكتلة.
يتم دعم الاستدعاءات المؤهلة مثل `vstd::prelude::verus!` أيضًا.
تحتفظ الدوال المساعدة المحلية بالدالة المحيطة بها في معرّفاتها (على سبيل المثال،
`file:outer.inner`). تُحل الاستدعاءات لهذه الدوال المساعدة والاستيرادات النسبية مثل
`use super::*` إلى التعريفات الموجودة في الملف.
تتلقى الأسماء المحلية المتكررة في كتل مختلفة لاحقة إزاحة بايتية للحفاظ على
تميز عقدها، وتحترم الاستدعاءات نطاق الكتلة.
تحتفظ البنى المحلية والتعدادات والسمات والوحدات المضمّنة بالدالة المحيطة
أيضًا: على سبيل المثال، `file:outer.Guard.drop` و`file:outer.local.helper`.
تحتوي أجسامها على استدعاءات وتعقيد منفصلين. تُحل الاستدعاءات الصريحة للأنواع
والوحدات المحلية المعروفة داخل الملف. تبحث الاستدعاءات المجردة في نطاقات
الدوال والوحدات؛ تستخدم العناصر المرتبطة مسارات مثل `Type::method`. تُحل الاستدعاءات
المنقطة فقط عندما يسمي المستقبل بنية أو تعدادًا معروفًا. تبقى مستقبلات القيم الأخرى،
بما في ذلك `self.method()`، غير محلولة. لا يتم نمذجة استدعاءات المدمر الضمنية
واستنتاج نوع المستقبل. تنطبق هذه القواعد على Rust العادي بالإضافة إلى
كتل Verus. يؤدي تحرير الكود قبل تعريف ذي لاحقة إزاحة إلى تغيير
معرّفه، لذا يمكن لـ `trailmark diff` الإبلاغ عن ذلك التعريف كمحذوف ومضاف.
لا يوسّع Trailmark وحدات الماكرو العشوائية. يتم تخطي استدعاءات Verus الحرفية داخل
وحدات الماكرو المعتمة أو أجسام الدوال مع تحذير. لا يتم توسيع تعريفات
`macro_rules!` غير المستدعاة. لا يتم استخراج توقيعات الدوال بدون أجسام
والاستدعاءات في جمل `requires`/`ensures`.
```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` (الوصول إلى السمات على كائنات غير ذاتية) أو `uncertain` (الإرسال الديناميكي أو الحل الملتبس).
### 2. الفهرس
يُحمّل `GraphStore` مخطط `CodeGraph` في `PyDiGraph` من rustworkx ويبني تعيينات ثنائية الاتجاه للمعرّفات/الفهارس لاجتياز سريع.
### 3. الاستعلام
يوفر `QueryEngine` واجهة برمجية عالية المستوى فوق المخطط المفهرس:
| الطريقة | الوصف |
| --- | --- |
| `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)` | إرجاع العُقد التي تحمل تعليقات من نوع النتائج |
| `subgraph(name)` | إرجاع العُقد في مخطط فرعي مسمّى |
| `subgraph_edges(name)` | إرجاع الحواف المستحثة داخل مخطط فرعي مسمّى |
| `subgraph_names()` | سرد كل مخطط فرعي مسمّى موجود حالياً على المخطط |
| `summary()` | أعداد العُقد وأعداد الحواف والتبعيات |
| `to_json()` | تصدير المخطط الكامل |
### نموذج البيانات
```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
```
**أنواع العُقد:** `function`، `method`، `class`، `module`، `struct`، `interface`، `trait`، `enum`، `namespace`، `contract`، `library`، `template`، `proxy`
**أصول العُقد:** `source`، `proxy`، `binary`، `synthetic`
**أنواع الحواف:** `calls`، `inherits`، `implements`، `contains`، `imports`، `resolves_to`، `type_uses`، `specializes`، `corresponds_to`
**ثقة الحواف:** `certain`، `inferred`، `uncertain`
تُجسَّد الاستدعاءات غير المحلولة كعُقد وكيلة مثل
`proxy.unresolved:<raw-symbol>` بحيث يمكن لنتائج التتبّع أن تُظهر أين فقد
تحليل الشيفرة المصدرية القدرة على الحل بدلًا من إسقاط تلك الحافة بصمت. كما
تُطبِّق عمليات تحليل الأدلّة، بما في ذلك تحليلات اللغة الواحدة، روابط
المستودع وتُجسِّد حواف `TYPE_USES`. يستورد دعم تحليل الملفات الثنائية رسوم
بيانية للاستدعاءات بصيغة JSON خارجية؛ ولا يقوم Trailmark بتفكيك الملفات
التنفيذية بنفسه.
### مثال على الرسم البياني
بالنظر إلى شيفرة Python التالية:
```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 يُنتج رسمًا بيانيًا مثل:
```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
```
## التثبيت
تتبع الأمثلة أدناه فرع التطوير الحالي. للحصول على أحدث
حزمة منشورة، ثبّتها من PyPI. للحصول على مجموعة الميزات الدقيقة الموصوفة
هنا، ثبّتها من نسخة مستخرجة من المستودع وشغّل الأوامر عبر `uv run`.
```bash
# Latest published release
uv pip install trailmark
# Current checkout / development branch
uv sync --all-groups
```
يتطلب Python ≥ 3.12.
يتطلب Trailmark الإصدار 1.22.1 أو أحدث من `tree-sitter-language-pack` لمعظم القواعد النحوية.
تُدعم ذاكرات التخزين المؤقت للقواعد النحوية المملوكة لجذر النظام عندما لا تكون قابلة للكتابة من قِبل المجموعة أو الآخرين.
تستخدم الإصدارات الحالية مخزن الشهادات الخاص بالمنصة لتنزيل القواعد النحوية. في
بيئات فحص TLS أو البيئات غير المتصلة بالإنترنت، املأ ذاكرة التخزين المؤقت للحزمة مسبقًا باستخدام
`python -c "import tree_sitter_language_pack as p; p.download_all()"` على
منصة مطابقة، ثم انسخ دليل ذاكرة التخزين المؤقت الناتج `tree-sitter-language-pack` إلى الجهاز الهدف. يُحترم أيضًا `HTTPS_PROXY`. تُشحن قاعدة SQL النحوية
كاعتمادية عجلة `tree-sitter-sql` ولا تستخدم ذاكرة التخزين المؤقت تلك.
تُترجم القواعد النحوية المرفقة Circom وMiden Assembly وVerus عند أول استخدام.
يتطلب ذلك مترجم C (`cc`)، وترويسات تطوير Python، وإذن الكتابة
إلى أدلة القواعد النحوية المثبتة الخاصة بها. لا تُطلق ملفات Rust التي لا تحتوي على كتل Verus
عملية الترجمة. إذا تعذّر بناء قاعدة Verus النحوية أو تحميلها، يسجّل Trailmark
تحذيرًا، ويتخطى كتل Verus، ويواصل تحليل Rust العادي.
تتضمن ذاكرة التخزين المؤقت لربط Verus محتويات المصدر المترجمة، وواجهة Python الثنائية (ABI)،
والمنصة، وخيارات المترجم. تؤدي المدخلات المتغيرة إلى اختيار ربط جديد؛ وتُنشر
عمليات البناء المكتملة بشكل ذرّي. تتضمن إخفاقات المترجم حالة الخروج و
stderr في التحذير.
تحتفظ عمليات سحب Git بتعريف قاعدة Verus النحوية وتولّد محللها اللغوي C أثناء
عمليات البناء باستخدام Tree-sitter CLI 0.27.1. قبل `uv sync` أو `uv build` في عملية سحب،
شغّل `npm ci` مع تمكين نصوص تثبيت npm؛ يلزم Node.js للتوليد.
يُستثنى المحلل اللغوي المولّد والترويسات من Git. تتضمن العجلات وتوزيعات المصدر
هذه المصادر المولّدة، لذا لا يتطلب تثبيت الحزم المنشورة Node.js
ولا Tree-sitter CLI.
تعيد عمليات تثبيت `uv` القابلة للتحرير تشغيل خطاف البناء لاستعادة الملفات المولّدة المفقودة؛
وتعيد المدخلات غير المتغيرة استخدام المخرجات الموجودة.
## الاستخدام
```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
```
### اكتشاف نقاط الدخول
يملأ Trailmark تلقائيًا `graph.entrypoints` بحيث تتوفر بيانات لـ `attack_surface()` وانتشار التلوث وعبور حدود الصلاحيات للعمل عليها. يتم الاكتشاف على أربع طبقات، كل منها تتجاوز التي قبلها:
1. **استدلال `main` العام.** أي دالة تُسمى `main` بأي لغة. تُوسم بـ `user_input` / `trusted_internal` / `low`.
2. **فحص واعٍ بإطار العمل.** أنماط المزخرفات والسمات والظهور لكل لغة — انظر الجدول أدناه.
3. **`pyproject.toml [project.scripts]`.** تحصل أهداف CLI الصريحة على تصنيف ثقة/أصل مُرقّى.
4. **ملف التجاوز المحلي للمستودع.** نقاط الدخول المُنسّقة يدويًا في `.trailmark/entrypoints.toml` تفوز دائمًا.
تغطية أطر العمل:
| اللغة | أطر العمل المكتشفة |
| --- | --- |
| 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، servlets |
| C# | ASP.NET Core، Azure Functions |
| PHP | سمات Symfony `#[Route]` + التعليقات التوضيحية القديمة |
| Rust | actix-web، rocket، تصديرات FFI (`#[no_mangle]`، `pub extern "C"`)، سمات async-main |
| Solidity | ظهور `external` / `public` |
| Cairo / StarkNet | `#[external]`، `#[view]`، `#[l1_handler]`، `#[constructor]` |
| Circom | تعريفات `component main` |
| Miden Assembly | توجيهات `export.<name>` |
| Haskell | `main ::` / `main =` على المستوى الأعلى |
| Erlang | الدوال المدرجة في `-export([...])` |
| Swift | سمة تطبيق `@main` |
| Objective-C | محددات دورة حياة `UIApplicationDelegate` (مثل `application:openURL:options:`) |
| Kotlin | تعليقات Spring MVC / WebFlux التوضيحية (مشتركة مع Java)، طرق دورة حياة مكونات Android (`onCreate`، `onReceive`، `onBind`، ...) |
| Dart | علامات الاستدعاء الأصلي `@pragma('vm:entry-point')` |
| Go | تسجيلات `http.HandleFunc` / `http.Handle` من المكتبة القياسية، تسجيلات المعالجات بنمط gin/chi/echo `<router>.GET/POST/...` |
| Ruby | إجراءات متحكم Rails (الفئات التي ترث `ApplicationController` / `ActionController::*`)، طرق `perform` لعامل Sidekiq |
| C / C++ | ارتباط `extern "C"`، `__attribute__((visibility("default")))`، `__declspec(dllexport)` |
لأي شيء تفوته الاستدلالات، صرّح بنقاط الدخول صراحةً في `.trailmark/entrypoints.toml` في جذر المشروع. يدعم الملف كلاً من الإدخالات أحادية العقدة والإدخالات القائمة على القواعد:
```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"
```
تُلغي الإدخالات اللاحقة الإدخالات السابقة عندما تُوسم قاعدتان العقدة نفسها، لذا ضع القواعد العامة أولًا ثم التصحيحات المحددة بعدها.
راجع [docs/entrypoint-patterns.md](https://github.com/trailofbits/trailmark/blob/main/docs/entrypoint-patterns.md) للحصول على المرجع الكامل، بما في ذلك الأُطر التي لم تُنفَّذ بعد (Express / Koa / Fastify، وLaravel، وCobra، وaxum، وwarp، وclap، وغيرها) مع أنماط جاهزة لـgrep يمكن للمساهمين استخدامها لإضافة كواشف جديدة.
يستخدم كشف Solidity بيانات وصفية من المحلّل بدلًا من تعبيرات نمطية للتوقيعات. تُستثنى
تعريفات الواجهات، وتُعلِّق التجاوزات المشتقة على تطبيقات الأساس المطابقة باستخدام
`solidity_overridden_by` بدلًا من إزالة نقطة الدخول الأساسية. تبقى الدوال الملموسة
`public` و`external` نقاط دخول، بما في ذلك دوال `view` و`pure`؛ وتُعاد سماتها
`solidity_visibility` و`solidity_mutability` والتجاوز بواسطة
`attack_surface()` حتى يتمكن المستدعون من التمييز بين التعرض للقراءة فقط وتصفية
تطبيقات الأساس المتجاوَزة. تتضمن `attack_surface()` سمات نقاط الدخول الخاصة بالمحلّل
عندما تكون مرتبطة بعقدة الرسم البياني الأساسية.
### الروابط العابرة للغات والروابط الخارجية
يدمج تحليل اللغات المتعددة رسوم اللغات البيانية، لكن العديد من علاقات RPC وFFI
والعمليات الفرعية وعلاقات المضيف/العقد ليست ظاهرة في صياغة المصدر. صرِّح عن هذه
العلاقات بشكل حتمي في `.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
```
قد تكون المراجع عبارة عن معرّفات عقد دقيقة أو أسماء/لواحق فريدة. المراجع الغامضة، ونقاط النهاية الداخلية غير المعروفة، وقيم التعداد غير الصالحة، وملفات TOML المشوّهة ترفع `ValueError`. تعيين `source_external = true` أو `target_external = true` يسمح صراحةً بنقطة النهاية غير المحلولة تلك وينشئ عقدة وكيل. هذا الملف واجهة تكوين عامة مستقرة.
### قيود التحليل
- `entrypoint_paths_to()` يبلّغ عن قابلية الوصول في رسم بياني للاستدعاءات، وليس عن تدفق بيانات يتحكم فيه المهاجم. استخدم نتائج التلوث من التحليل المسبق كإشارة منفصلة تقريبية؛ لا يقوم Trailmark بعد بإجراء تحليل تلوث بين الإجراءات.
- يحل TypeScript الاستدعاءات المباشرة والمستقبِلات المباشرة المعيّنة بـ `new ConcreteClass()`. يظل الإرسال عبر الواجهات من خلال البيانات الوصفية، وأسماء الخصائص المحسوبة، وحاويات حقن التبعيات، وغيرها من الآليات الديناميكية بأفضل جهد ممكن.
- دعم SQL موجّه نحو PostgreSQL ويستخرج المخططات والجداول والعروض والدوال والإجراءات وتبعيات الروتينات/العروض. وهو ليس مدققًا كاملًا لهجات SQL ولا محللًا لدلالات الاستعلامات.
### واجهة برمجة التطبيقات البرمجية
```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
```
---
[Read more](https://github.com/trailofbits/trailmark)