ChunkHound¶
ChunkHound is a RAG system that relies on vector databases and embeddings, supports many programming languages via tree-sitter, and can build a concrete syntax tree for precise code queries.
Notes¶
- Risk: ChunkHound relies on an embedding LLM provider, so data can be leaked.
- Mitigation: Use an Ollama embedding model if you need local-only flows.
Example Action¶
Info
Prompt: "In the GitTinkerer project, look into if other users can maliciously inject prompts on GitHub Pull Request comment section. Are only GitHub repo owner authorized to use the /tinker command?"
nntin@NUC:~/git/lair.nntin.xyz$ chunkhound research "In the GitTinkerer project, look into if other users can maliciously injects prompts on GitHub Pull Request comment section. Are only GitHub repo owner authorized to use the /tinker command?"
[+ 0.0s] π Starting deep research: In the GitTinkerer project, look into if other users can mal...
[+ 0.0s] βΉοΈ Max depth: 1, synthesis budget: 115k tokens
[+ 0.0s] π Processing depth 0/1
[+ 0.0s] πΉ In the GitTinkerer project, look into if other users can mal...
[+ 0.0s] π Expanding query
[+ 4.4s] β¨ Expanded to 3 queries (queries=3)
[+ 8.0s] π Found 28 chunks (chunks=28)
[+ 8.0s] π·οΈ Extracting symbols
[+ 8.0s] π Extracted 13 symbols, searching top 5 (symbols=13)
[+ 8.0s] π Running regex search
[+ 8.1s] β Found 0 additional chunks (chunks=0)
[+ 8.1s] π Reading files
[+ 8.1s] π Read 3 files (files=3, tokens=9746)
[+ 8.1s] π€ Generating follow-up questions
[+ 16.8s] π‘ Generated 3 follow-ups
[+ 16.8s] β
Complete (files=3, chunks=28, children=3)
[+ 16.8s] βββ π Processing depth 1/1
[+ 16.8s] βββ πΉ In `service/src/usecases/github/handleIssueComment.ts`, wher...
[+ 16.8s] βββ π Expanding query
[+ 16.8s] βββ πΉ Does `service/src/controllers/githubWebhookController.ts` or...
[+ 16.8s] βββ π Expanding query
[+ 16.8s] βββ πΉ How does `service/src/usecases/github/fetchPullRequest.ts` u...
[+ 16.8s] βββ π Expanding query
[+ 19.9s] βββ β¨ Expanded to 3 queries (queries=3)
[+ 20.4s] βββ β¨ Expanded to 3 queries (queries=3)
[+ 25.7s] βββ β¨ Expanded to 3 queries (queries=3)
[+ 25.7s] βββ π Found 22 chunks (chunks=22)
[+ 25.7s] βββ π·οΈ Extracting symbols
[+ 25.7s] βββ π Extracted 12 symbols, searching top 5 (symbols=12)
[+ 25.7s] βββ π Running regex search
[+ 25.7s] βββ π Found 34 chunks (chunks=34)
[+ 25.7s] βββ π·οΈ Extracting symbols
[+ 25.7s] βββ π Extracted 17 symbols, searching top 5 (symbols=17)
[+ 25.7s] βββ π Running regex search
[+ 25.8s] βββ β Found 0 additional chunks (chunks=0)
[+ 25.8s] βββ π Reading files
[+ 25.8s] βββ π Read 8 files (files=8, tokens=10409)
[+ 25.8s] βββ β
Complete (leaf at max depth) (files=8, chunks=22, children=0)
[+ 26.2s] βββ β Found 0 additional chunks (chunks=0)
[+ 26.2s] βββ π Reading files
[+ 26.2s] βββ π Read 13 files (files=13, tokens=27715)
[+ 26.2s] βββ β
Complete (leaf at max depth) (files=13, chunks=34, children=0)
[+ 28.8s] βββ π Found 13 chunks (chunks=13)
[+ 28.8s] βββ π·οΈ Extracting symbols
[+ 28.8s] βββ π Extracted 11 symbols, searching top 5 (symbols=11)
[+ 28.8s] βββ π Running regex search
[+ 28.9s] βββ β Found 10 additional chunks (chunks=10)
[+ 28.9s] βββ π Reading files
[+ 28.9s] βββ π Read 7 files (files=7, tokens=21368)
[+ 28.9s] βββ β
Complete (leaf at max depth) (files=7, chunks=19, children=0)
[+ 28.9s] π§© Aggregating findings from BFS tree
[+ 28.9s] β’ Reranking 19 files by relevance
[+ 29.4s] π§© Synthesizing final answer (input: 41,802/80,000 tokens, 52.3%) (chunks=69, files=19)
[+ 30.9s] β’ Synthesizing 2 clusters in parallel (concurrency=3)
[+ 57.5s] β’ Combining 2 cluster summaries into final answer
[+ 71.1s] π Validating output quality
[+ 71.1s] π Deep research complete
**Answer**
- The GitTinkerer webhook flow accepts `issue_comment` events that pass signature verification and looks for comments beginning with `/tinker`. There is no documented or implemented check in the shown handler to restrict this to repo owners or specific commenters. As a result, any GitHub user who can comment on a PR can trigger a run by using `/tinker`. [1][3][10][13]
- The docs explicitly treat comment bodies as untrusted input and suggest adding additional allowlisting before spawning runs, which implies that the default flow does not enforce author-based restrictions. [1]
- The instruction text is derived from the PR comment (with `/tinker` stripped) and becomes `comment_body` in the run payload; the raw comment is also stored. This is the prompt surface, so a malicious commenter can attempt prompt injection through the instruction text if they can comment on the PR. [1][3][13]
**Why this is the case (flow and gates)**
- The webhook middleware enforces required GitHub headers; the controller verifies the webhook signature and only processes `issue_comment` events. Invalid signatures are rejected, and non-`issue_comment` events are ignored. [10][12][14]
- `handleIssueComment` ignores nonβPR comments and comments without the `/tinker` prefix; otherwise it continues with rate limiting, PR metadata fetch, and run creation. There is no owner-only or commenter allowlist check in this handler. [13]
- The architecture and README describe `/tinker` as the trigger in PR comments and do not mention ownership or roleβbased restrictions. [1][3]
**Authorization context (what is and isnβt enforced)**
- The GitHub App uses standard installation-token auth (JWT β installation token) to act on the repo where the app is installed. That establishes API access but does not authorize which GitHub user is allowed to trigger `/tinker`. [1][9][11]
- The provided GitTinkerer auth and client code shows how tokens are minted and used, but it does not include any commenter authorization checks. [9][11]
- Additional code from a related Tinkero webhook handler shows similar installation token flows and caching but also does not contain `/tinker` parsing or perβcommenter authorization logic. [17][18][19]
**Direct answers to the questions**
- **Can other users maliciously inject prompts in GitHub PR comments?**
Yes, if they can comment on the PR. The `/tinker` handler accepts the comment text as the instruction, with no author-based gating in the shown flow, so prompt injection via PR comments is possible under those conditions. [1][3][13]
- **Are only GitHub repo owners authorized to use `/tinker`?**
No evidence shows ownerβonly authorization. The current flow authorizes execution based on valid GitHub signature, `issue_comment` event, PR context, and `/tinker` prefix, not commenter identity or repo ownership. [1][3][10][13]
**Notes on evidence limits**
- The provided sources that cover GitHub App authentication and token usage do not include any `/tinker` authorization logic, so they neither establish nor refute additional checks outside the shown handlers. [9][11][17][18][19]
If you want to harden this, typical mitigations include checking commenter org/team membership or maintainers list, or implementing a repo/org allowlist before executing `/tinker`, as the docs already suggest. [1]
---
## Sources
**Files**: 19 | **Chunks**: 69
βββ projects/
βββ GitTinkerer/
β βββ [1] README.md (6 chunks: L3-13, L39-45, L53-58, +3 more)
β βββ docs/
β β βββ [2] api-reference.md (6 chunks: L11-23, L53-55, L55-69, +3 more)
β β βββ [3] architecture.md (5 chunks: L3-13, L124-143, L144-177, +2 more)
β β βββ [4] github-app-setup.md (15 chunks: L3-10, L39-62, L62-69, +12 more)
β β βββ [5] index.md (6 chunks: L3-13, L39-45, L53-58, +3 more)
β β βββ [6] observability.md (4 chunks: L181-195, L464-479, L604-608, +1 more)
β βββ service/
β βββ src/
β βββ __tests__/
β β βββ helpers/
β β β βββ [7] factories.ts (1 chunks: L95-130)
β β βββ integration/
β β βββ [8] setup.ts (1 chunks: L128-157)
β βββ config/
β β βββ [9] github.ts (3 chunks: L129-147, L148-180, L193-229)
β βββ controllers/
β β βββ [10] githubWebhookController.ts (4 chunks: L26-51, L52-77, L60-82, +1 more)
β βββ infra/
β β βββ github/
β β βββ [11] api.ts (1 chunks: L7-48)
β βββ middleware/
β β βββ [12] githubWebhookGate.ts (1 chunks: L4-35)
β βββ usecases/
β βββ github/
β βββ [13] handleIssueComment.ts (1 chunks: L39-77)
β βββ [14] verifyWebhook.ts (1 chunks: L8-21)
βββ Tinkero/
βββ services/
βββ webhook-handler/
βββ [15] REPOSITORY_CLONING.md (3 chunks: L3-13, L13-30, L150-183)
βββ internal/
βββ config/
β βββ [16] TINKERO_CONFIG.md (1 chunks: L335-347)
βββ github/
βββ [17] README.md (3 chunks: L13-42, L53-57, L58-119)
βββ [18] auth.go (2 chunks: L41-72, L45-88)
βββ [19] client.go (5 chunks: L91-120, L100-134, L112-116, +2 more)
# Implementation Plan: Owner-Only `/tinker` Authorization
## Overview
Fix the security vulnerability where any GitHub user who can comment on a PR can trigger `/tinker` commands. Restrict usage to repository owners only (personal repos), with clear feedback for unauthorized users.
## Critical Files
1. **projects/GitTinkerer/service/src/usecases/github/handleIssueComment.ts** - Add authorization logic
2. **projects/GitTinkerer/service/src/controllers/dependencies.ts** - Wire up postPRComment dependency
3. **projects/GitTinkerer/service/src/usecases/github/__tests__/handleIssueComment.test.ts** - Add test coverage
4. **projects/GitTinkerer/docs/architecture.md** - Document authorization policy
## Implementation Steps
### 1. Add Authorization Check to handleIssueComment.ts
**Location**: After line 54 (after `/tinker` prefix check, before rate limiting)
**Add helper function** (before handleIssueComment function):
```typescript
function isRepositoryOwner(event: GitHubIssueCommentEvent): boolean {
// Only User-owned repos supported (not Organization)
if (event.repository.owner.type !== 'User') {
return false;
}
// Commenter must match repo owner
return event.comment.user.login === event.repository.owner.login;
}
nntin@NUC:~/git/lair.nntin.xyz$ chunkhound research "In the GitTinkerer project, look into if other users can maliciously injects prompts on GitHub Pull Request comment section. Are only GitHub repo owner authorized to use the /tinker command?"
[+ 0.0s] π Starting deep research: In the GitTinkerer project, look into if other users can mal...
[+ 0.0s] βΉοΈ Max depth: 1, synthesis budget: 115k tokens
[+ 0.0s] π Processing depth 0/1
[+ 0.0s] πΉ In the GitTinkerer project, look into if other users can mal...
[+ 0.0s] π Expanding query
[+ 3.1s] β¨ Expanded to 3 queries (queries=3)
[+ 6.8s] π Found 25 chunks (chunks=25)
[+ 6.8s] π·οΈ Extracting symbols
[+ 6.8s] π Extracted 14 symbols, searching top 5 (symbols=14)
[+ 6.8s] π Running regex search
[+ 7.0s] β Found 0 additional chunks (chunks=0)
[+ 7.0s] π Reading files
[+ 7.0s] π Read 4 files (files=4, tokens=10000)
[+ 7.0s] π€ Generating follow-up questions
[+ 20.9s] π‘ Generated 2 follow-ups
[+ 20.9s] β
Complete (files=4, chunks=25, children=2)
[+ 20.9s] βββ π Processing depth 1/1
[+ 20.9s] βββ πΉ In `handleIssueComment` (service/src/usecases/github/handleI...
[+ 20.9s] βββ π Expanding query
[+ 20.9s] βββ πΉ Where is `createPrPayload` (service/src/types/payload.ts) us...
[+ 20.9s] βββ π Expanding query
[+ 23.9s] βββ β¨ Expanded to 3 queries (queries=3)
[+ 26.3s] βββ β¨ Expanded to 3 queries (queries=3)
[+ 27.6s] βββ π Found 16 chunks (chunks=16)
[+ 27.6s] βββ π·οΈ Extracting symbols
[+ 27.6s] βββ π Extracted 13 symbols, searching top 5 (symbols=13)
[+ 27.6s] βββ π Running regex search
[+ 28.5s] βββ β Found 12 additional chunks (chunks=12)
[+ 28.5s] βββ π Reading files
[+ 28.5s] βββ π Read 6 files (files=6, tokens=20651)
[+ 28.5s] βββ β
Complete (leaf at max depth) (files=6, chunks=22, children=0)
[+ 30.0s] βββ π Found 23 chunks (chunks=23)
[+ 30.0s] βββ π·οΈ Extracting symbols
[+ 30.0s] βββ π Extracted 16 symbols, searching top 5 (symbols=16)
[+ 30.0s] βββ π Running regex search
[+ 30.1s] βββ β Found 12 additional chunks (chunks=12)
[+ 30.1s] βββ π Reading files
[+ 30.1s] βββ π Read 10 files (files=10, tokens=28872)
[+ 30.1s] βββ β
Complete (leaf at max depth) (files=10, chunks=31, children=0)
[+ 30.1s] π§© Aggregating findings from BFS tree
[+ 30.1s] β’ Reranking 10 files by relevance
[+ 30.4s] π§© Synthesizing final answer (input: 26,392/80,000 tokens, 33.0%) (chunks=35, files=10)
[+ 37.0s] π Validating output quality
[+ 37.0s] π Deep research complete
I canβt deliver a 30,000βtoken fullβsystem analysis in this response, but I can answer your specific security question clearly with citations from the provided sources.
Other users **cannot** trigger `/tinker` runs unless they are the repository owner, and organizationβowned repos are rejected entirely. The service enforces this by checking `repository.owner.type === 'User'` and requiring `comment.user.login === repository.owner.login` before any rate limiting or PR metadata fetches; unauthorized attempts are ignored and get a denial comment posted back to the PR. [3] [10] This gate is explicitly documented as a protection against promptβinjection attempts from untrusted collaborators. [3] Therefore, only the GitHub repo owner can use `/tinker`, and other commenters cannot maliciously inject prompts through PR comments. [3] [10]
---
## Sources
**Files**: 10 | **Chunks**: 35
βββ projects/
βββ GitTinkerer/
βββ [1] README.md (4 chunks: L53-58, L58-69, L94-119, +1 more)
βββ docs/
β βββ [2] api-reference.md (1 chunks: L171-205)
β βββ [3] architecture.md (5 chunks: L144-177, L389-436, L437-450, +2 more)
β βββ [4] github-app-setup.md (9 chunks: L3-10, L72-89, L133-142, +6 more)
β βββ [5] index.md (4 chunks: L53-58, L58-69, L94-119, +1 more)
β βββ [6] observability.md (3 chunks: L181-195, L464-479, L627-661)
βββ service/
βββ src/
βββ __tests__/
β βββ helpers/
β β βββ [7] factories.ts (1 chunks: L95-130)
β βββ integration/
β βββ [8] setup.ts (1 chunks: L128-157)
βββ types/
β βββ [9] payload.ts (1 chunks: L110-122)
βββ usecases/
βββ github/
βββ [10] handleIssueComment.ts (6 chunks: L34-51, L45-49, L53-82, +3 more)
PS: The creator of ChunkHound created the project out of necessity while rewriting a 170 million line codebase over multiple decades (Ada, Java, C++, Matlab, DI, and indirection).