coming soon
Broken access control tops the OWASP Top 10. A refactor that drops one ownership check looks fine in review, and it passes every test that signs in as the right user. Security checks catch it before the merge. CI starts the PR's build as a throwaway preview, and Talooner checks it against an access policy declared in the repository. One to three cooperating agents each act as a different role. Results come back as facts, and a rule blocks the merge on any violation.
The model plans and proposes scenarios. It never decides the outcome: a finding counts only when the runner reproduces it deterministically.
What it doesn't cover
- Anything outside the pipeline's own preview environment.
- Background jobs, webhooks, mobile clients and infrastructure.
- Real user data or real credentials.
What you provide in CI
-
A preview deployment of the PR, reachable from the job, passed in as
TALOONER_ACCESS_TARGET(e.g.https://pr-412.preview.acme.dev). -
Seed data and test accounts, created by your own CI step. Credentials reach the runner as one masked variable,
TALOONER_ACCESS_ACCOUNTS(base64 YAML):login: url: /api/session # how a role signs in; the runner keeps the session body: '{"email":"{{email}}","password":"{{password}}"}' roles: guest: {} # no session member_a: { email: a@test.acme.dev, password: … , tenant: team-a } member_b: { email: b@test.acme.dev, password: … , tenant: team-b } admin: { email: admin@test.acme.dev, password: … } -
The policy, in the repository: the
.talooner/access/folder.
The policy
The policy is a folder of plain tln files, loaded together. Split it however your app is split: one file per area keeps each rule next to the team that owns it.
.talooner/access/
├── guests.tln
├── tenants.tln
└── admin.tln
Each route or resource the runner reaches is a record. The role the agent is acting
as arrives as context.actor and context.tenant. Anything a rule blocks must stay
out of reach for that role:
// .talooner/access/guests.tln
// Only sign-in and health checks are open without a session.
strict rule "Guests stay out of the API" {
for records where type == "endpoint"
and attr "path" starts_with "/api/"
and attr "path" not in ["/api/session", "/api/health"]
and context.actor == "guest"
block "access"
reason "API routes need a session"
}
// .talooner/access/tenants.tln
// One tenant never sees another tenant's data.
strict rule "Members stay in their own tenant" {
for records where type == "project"
and context.actor == "member"
and attr "tenant" != context.tenant
block "access"
reason "cross-tenant access"
}
// .talooner/access/admin.tln
// Admin screens are for admins.
strict rule "Admin area is admin-only" {
for records where type == "endpoint"
and attr "path" starts_with "/admin"
and context.actor != "admin"
block "access"
reason "admin-only route"
}
The rules are strict, so nothing else in the ruleset can override them.
Gating the merge
Every violation the runner reproduces becomes a fact on the PR. Your review ruleset gates on it like on any other fact:
rule "Block on access violations" {
for records where type == "pr"
and attr "security.violations_count" > 0
block "merge"
do block "pr.merge"
do comment "pr" "Access policy violated: {attr.security.violations}. Each one reproduced against the preview"
reason "access policy violated"
priority CRITICAL
}
Where this is headed: red-team agents
The roles above are fixed probes. The direction we're exploring is a group of agents that collaborate to discover access and authorization flaws — a multi-agent red team, pointed only at software you've authorized and running in the preview's isolated sandbox. Each agent has a specialised role and shares findings through a private channel; a coordinator hands out the work and uses what comes back to decide what to look at next.
The agents
| Agent | Responsibility |
|---|---|
| Scout | Maps the app's surface and flags components worth a closer look |
| Analyst | Reads the code and forms vulnerability hypotheses |
| Tester | Runs controlled, benign tests against the isolated copy |
| Critic | Independently checks findings and throws out false positives |
The coordinator distributes the work and uses the agents' feedback to choose the next thing to investigate.
Black box or white box
How much the agents get to see is up to you, set per repo.
- Black box — the agents see only the running preview, the way an outside user would. They map the surface and probe it without reading a line of source. Good for catching what's actually reachable, independent of what the code intends.
- White box — the agents also read the diff and the source. The Analyst can reason straight from the implementation to a hypothesis, so a dropped ownership check is found by looking, not just by guessing which request to send.
Because the PR gives Talooner both the preview and the repository, it can run either — or white box to form the hypothesis and black box to prove it against the live app.
Limits
The red team runs inside the CI job, so it stays bounded and predictable:
- Time — a wall-clock budget per run; when it's up, the agents stop and report what they have so far.
- Retries — a probe that fails to reproduce is retried a fixed number of times before it's dropped. A finding counts only once the runner reproduces it deterministically, so a flaky one never reaches the verdict.
- Budget — a cap on model calls and requests per run, so cost stays flat whatever the agents decide to chase.
- Scope — the agents touch only the authorized preview and its seed data; the sandbox and its audit log are the fence.
Hit a limit and the run ends cleanly with a partial result — never a hang, and never a merge blocked just because the budget ran out.
A collaboration cycle
- Scout spots an API endpoint with unusual input handling.
- Analyst reads the implementation behind it and proposes a possible authorization flaw.
- Tester runs benign cases against a locally isolated copy of the app.
- Critic checks whether the observed behaviour actually breaks the intended security policy.
- Coordinator consolidates the evidence and recommends a fix or another test.
Everything stays in bounds: the targets are ones you've authorized, and the whole run happens in an isolated sandbox with audit logs.
Want security checks on your repos early? Tell us.