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:jiesou/dsh-stream-rules
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
Inject rules when needed, without wasting context.
You can write custom streaming rules for the agent.
These rules are injected only as a steering notice after a pattern match, then agent retry from the same point. This allows you to control the boundaries of agent behavior, without wasting context.
Port of my jiesou/opencode-stream-rules to DSH. Similar to oh-my-pi's "Time-traveling stream rules", but with a very simple and compact code implementation.
A rule fires when its match returns true, against:
timeoutMs), before dispatch.[timed out after 600000ms], [exit code: 1], …) and error text join the match string, so rules describing outcomes (a crash, a full disk, a timeout) can match there too. Matching after dispatch can only steer, never deny.On a match:
SYSTEM NOTICE steering message into the agent (pre-dispatch via agent.inject(), post-dispatch as additionalContexts on the tool result — DSH's non-waking "queue model-facing context for the next pre-step"). The agent retries from the same point, now knowing the rule.reject: true — denies the FIRST tool call ({ kind: 'deny' }); later attempts are allowed. Steering without over-restricting, e.g. letting pip install through when it's already in a container.Each rule fires at most once per session (per agent), mirroring the original's notified dedup.
From npm (prebuilt, recommended):
dsh plugin --profile <name> add @jiesou/dsh-stream-rules
Or from GitHub (runs prepare to build on install):
dsh plugin --profile <name> add github:jiesou/dsh-stream-rules
Or add the row to your profile's cordis.patch.yml:
- id: stream-rules
name: '@jiesou/dsh-stream-rules'
You need to write the rules in your own .js file. This plugin won't work by default until you edit the rules.
$DSH_HOME/profiles/<name>/node_modules/@jiesou/dsh-stream-rules
where $DSH_HOME defaults to ~/.dsh.
mv rules/rules.js.example rules/rules.local.js
_ are skipped.config.rules:- id: stream-rules
name: '@jiesou/dsh-stream-rules'
config:
rules: /path/to/your/rules
reject: true will only be rejected on the first toolcall; subsequent attempts by the agent will be allowed. This provides steering while avoiding overly restricting the model (e.g., allowing pip install if it's already in a container).// rules/rules.local.js
export default [
{
match: (v) =>
v.includes('pip') &&
v.includes('install') &&
!v.includes('uv pip') &&
!v.includes('uvx'),
reject: true,
prompt: 'Use `uvx` or `uv venv` + `uv pip` instead of `pip install` directly',
},
{
match: (v) => v.includes('curl') && v.includes('api.github.com'),
prompt: 'Prefer using `gh` cli over `curl https://api.github.com/...`. gh offers more requests limits.',
},
{
match: (v) => v.includes('pdf'),
prompt: 'Use the `markitdown` skill to read PDF files.',
},
// add your rules here
]
| field | required | description |
|---|---|---|
match |
✅ | (v: string) => boolean; every tool call is flattened to a string and matched — plus, after dispatch, the settled result's content, markers and error text |
prompt |
✅ | The prompt for steering |
reject |
If true, prevent the tool call first, instead of just steering |
Declared in package.json under dsh.compatibility: DSH >=0.1.7-alpha.1 <0.2, Node.js ^22.19.0 || >=24.0.0, profiles web / headless.
>=0.1.7-alpha.1 is a hard floor, not a preference: that release retires the { kind: 'plugin', plugin: … } message source (session format v4), so the steering notice declares its own MessageSourceMap entry.
Per-release evidence (each release installed into a disposable profile with dsh plugin add <tarball>): the profile composes and cold-starts, the tool-call hook is exercised directly against that release's tools/pre-execute waterfall and agent.inject() (steering notice delivered, reject: true denies the first call and allows the retry), then the plugin is uninstalled and the profile boots again. The rows below are the evidence collected for the >=0.1.0-rc.6 declaration; the range declared above is not re-verified release by release yet.
| DSH version | install | start | hook | uninstall |
|---|---|---|---|---|
| 0.1.5-alpha.1 | passed | passed | passed | passed |
| 0.1.5-alpha.2 | passed | passed | passed | passed |
| 0.1.5-rc.1 | passed | passed | passed | passed |
src/index.ts (~80 lines).tools/pre-execute waterfall (deny), tools/post-execute (failure-text matching + additionalContexts) and agent.inject() (steering), the documented native extension points. No core changes, no monkey-patching.CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: guardrail。