api-relay-audit
toby-bridges
Local security audit for AI API relays and LLM proxies: detects prompt injection, model substitution, tool-call rewriting, SSE anomalies, error leakage, and Web3 wallet risks.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:imroc/dsh-project-prompt
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
English | 中文
Private, per-project prompt rules for DeepSeek Harness (DSH).
Some agent instructions belong to your machine, not to the repository: environment-specific E2E procedures, internal-only endpoints, personal workflow preferences. AGENTS.md is committed and shared, so it is the wrong place for them. This plugin keeps such text in $DSH_HOME, never in the repo, and injects it into every session whose workspace matches a rule — including every subagent and every git worktree of the repository.
flowchart LR
subgraph repo["git repository (any clone / worktree / subdir)"]
wt1["main checkout"]
wt2["linked worktree A"]
wt3["worktree B"]
end
cfg["$DSH_HOME/cordis.patch.yml\nrules (machine-local, private)"]
plugin["dsh-project-prompt\nagent/session-start listener"]
sp["session system prompt\n(or first injected message)"]
cfg --> plugin
wt1 & wt2 & wt3 -->|match by remote / repo / path| plugin
plugin -->|section / inject| sp
remote URL (any clone, anywhere on disk), by local main-repo path, or by plain cwd prefix. Keys within a rule are OR-combined..git file's gitdir: pointer, so a rule written once covers worktrees created later, and their subdirectories.section (a stable system-prompt segment, KV-cache friendly, supports {{cwd}}/{{model}}) and inject (a first context message, no template interpolation — use it when the text contains literal {{...}} braces, e.g. Helm or Go templates).text, unknown {{var}} in section mode) throw when the plugin loads, not on every request.0.1.1-rc.2 (uses the agent/session-start event, systemPrompt.section, and agent.inject extension points).Install into a profile with DSH's plugin command:
dsh plugin --profile web add dsh-project-prompt
# or install straight from the GitHub repository:
dsh plugin --profile web add github:imroc/dsh-project-prompt
Restart DSH afterwards — bundles are composed at startup.
Uninstall:
dsh plugin --profile web remove dsh-project-prompt
Rules live in $DSH_HOME/cordis.patch.yml (~/.dsh/cordis.patch.yml by default) — the machine-local layer that applies to every profile on the machine. Override the row the bundle installed:
- id: project-prompt
config:
rules:
# Matches this repository wherever it is cloned, and in all worktrees.
- remote: github.com/my-org/my-project
text: |
## E2E testing for this project (environment-specific, private)
1. Test entry point: http://e2e.internal.example.net (internal only)
2. Run `make e2e-prepare` before the first E2E run.
3. On failures, check ... first.
# Matches by local main-repo path; the rule text contains literal
# {{...}} braces, so it must use inject mode.
- repo: /home/me/dev/another-project
mode: inject
text: |
Render values like {{ .Values.replicas }} are literal here.
# Matches any session started under a plain directory prefix.
- path: /home/me/dev
text: |
...
The file is watched for changes — saving it hot-reloads the plugin row (take effect for sessions started afterwards).
| Key | Type | Default | Description |
|---|---|---|---|
remote |
string | — | Git remote URL (origin) to match. Compared after normalization: scheme, user@, scp-style : separator, trailing .git and slashes, and case are ignored. git@github.com:u/r.git ≡ https://github.com/u/r. A bare host/org/repo suffix also matches. |
repo |
string | — | Local absolute path of the git main repository. Any linked worktree and any subdirectory of it matches (worktrees are traced back via the .git gitdir pointer). |
path |
string | — | Cwd prefix: the session workspace equals this directory or lives underneath it. |
text |
string | required | The prompt text to inject. |
mode |
section | inject |
section |
Injection mode, see below. |
sectionName |
string | project-prompt (auto-increments when several section rules match one session) |
System-prompt section name. |
order |
number | 50 |
System-prompt section order (DSH conventions: 0 persona, 100–199 tool guidance). |
A rule needs at least one of remote / repo / path; several matching rules all apply.
section (default) |
inject |
|
|---|---|---|
| Lands as | System-prompt segment on the agent-scoped systemPrompt service |
First user-side context message (same path AGENTS.md content takes) |
| Visible | Every request of the session | Every request of the session |
| Template interpolation | Yes — {{cwd}} and {{model}} resolve; any other complete {{...}} group throws |
No — braces are literal |
| Best for | Stable instructions; KV-cache-friendly | Text containing literal {{...}} (Helm/Go templates, Terraform, etc.) |
The plugin validates section text at load time: an unknown {{var}} fails the load with a message telling you to switch that rule to mode: inject.
agent/session-start synchronously before the first model request of every new session (fresh, resumed, after clear/compact — each publish mints a new agent scope).agent.session.header.cwd and tests each rule; git repository identity is resolved by walking up from the cwd to .git (a file means a linked worktree, whose gitdir: pointer leads back to the main repository root and its remote URLs).agent.ctx — the agent-scoped context — so it applies to that agent only and is discarded with it."Model-visible means logged": injected sections appear in the request headers recorded in the session log ($DSH_HOME/sessions/…), which is also how you verify a rule landed.
dsh --profile web --dump-config | grep -A3 project-prompt.session.jsonl.zstd contains the assembled system prompt with your section.remote rule (that is usually the point)..git pointing into .git/modules/…) are not traced; use a path rule for them.AGENTS.md/CLAUDE.md loading.git clone github:imroc/dsh-project-prompt && cd dsh-project-prompt
npm test # node --test; git fixtures are created in a temp dir
node --check index.js
The plugin is a single dependency-free ESM file; the committed source is the shipped artifact (no build, no prepare script — which is also why git installs need no pnpm allowBuilds entry). See AGENTS.md for the constraints that keep it that way.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: prompt-injection。