Priority: low — non-urgent. No exploit path today. Defense-in-depth hardening for a future-proofing scenario. Surfaced by adversarial review of the v4.1.0 release.
Context
v4.1.0 added pipeline-controller to the BOOTSTRAP_AGENTS whitelist in .claude/hooks/sentinel-hook.cjs to fix the cold-start bug (PR #3). The fix works correctly. This issue is about a latent improvement in the same area.
What the check does today
.claude/hooks/sentinel-hook.cjs:113-131:
const agentName = agentType.split(':').pop();
// ...
const BOOTSTRAP_AGENTS = ['task-orchestrator', 'pipeline-controller'];
if (BOOTSTRAP_AGENTS.includes(agentName)) {
return process.exit(0); // fail-open: bootstrap permitted
}
The whitelist is compared against the last segment of subagent_type, not the full path.
The latent risk
A hypothetical subagent_type like someplugin:something:pipeline-controller would also pass the whitelist check. Currently this is impossible because line 109 filters startsWith('pipeline-orchestrator:') first — only agents owned by this plugin reach the whitelist comparison. So the latent vector is fully closed today.
The risk only materializes if another plugin in the future adopts the pipeline-orchestrator: prefix (intentionally or by accident), which would expand the whitelist implicitly.
Proposed fix (~2 lines)
Compare the full fully-qualified subagent_type instead of the last segment:
const FQ_BOOTSTRAP = [
'pipeline-orchestrator:core:task-orchestrator',
'pipeline-orchestrator:core:pipeline-controller'
];
if (FQ_BOOTSTRAP.includes(agentType)) {
return process.exit(0);
}
Behavior is identical today. The change closes the latent vector at zero behavioral cost.
Acceptance criteria
Where to ship
Suggested release: v4.1.1 patch — bundled with any next behavioral change, no rush.
Discovery
Adversarial review of v4.1.0 release artifacts (Real-1 finding).
Context
v4.1.0addedpipeline-controllerto theBOOTSTRAP_AGENTSwhitelist in.claude/hooks/sentinel-hook.cjsto fix the cold-start bug (PR #3). The fix works correctly. This issue is about a latent improvement in the same area.What the check does today
.claude/hooks/sentinel-hook.cjs:113-131:The whitelist is compared against the last segment of
subagent_type, not the full path.The latent risk
A hypothetical
subagent_typelikesomeplugin:something:pipeline-controllerwould also pass the whitelist check. Currently this is impossible because line 109 filtersstartsWith('pipeline-orchestrator:')first — only agents owned by this plugin reach the whitelist comparison. So the latent vector is fully closed today.The risk only materializes if another plugin in the future adopts the
pipeline-orchestrator:prefix (intentionally or by accident), which would expand the whitelist implicitly.Proposed fix (~2 lines)
Compare the full fully-qualified
subagent_typeinstead of the last segment:Behavior is identical today. The change closes the latent vector at zero behavioral cost.
Acceptance criteria
sentinel-hook.cjscompares fullsubagent_typeagainst an FQN whitelist[6](task-orchestrator bootstrap) still passes[6b](pipeline-controller bootstrap) still passessomeplugin:nested:pipeline-controlleris denied (not bootstrapped)Where to ship
Suggested release:
v4.1.1patch — bundled with any next behavioral change, no rush.Discovery
Adversarial review of v4.1.0 release artifacts (Real-1 finding).