Security guide#
Least-privilege credentials#
| Integration | Grant | Do not grant |
|---|---|---|
| Jira (each person, optional) | Their own API token / personal access token, used only to read the projects, sprints and stories they can see; stored encrypted, deleted on Disconnect | Sharing tokens between people |
| Jira (bot account) | Browse projects, Add comments, Create attachments, Transition issues (only if Jira status updates are on) โ in the pilot projects only | Administer, Delete, project admin |
| GitLab | Project access token, role Developer, scopes api, read_repository, write_repository; protect main so Developers cannot push or merge to it |
Maintainer/Owner, group tokens, personal tokens of people |
| GitHub | Fine-grained token for the repositories: Contents write, Pull requests write, Actions read, Metadata read; branch protection with required reviews on main |
Administration, Workflows write, classic tokens |
| Anthropic API | A dedicated workspace key with a spend limit | Organisation admin keys |
| Amazon Bedrock | bedrock:InvokeModel / InvokeModelWithResponseStream on the exact model/inference-profile ARNs, in ap-south-1 for data residency |
bedrock:*, other regions |
| S3 artifacts | s3:PutObject, s3:GetObject, s3:ListBucket on arn:aws:s3:::<bucket>/sprintflow/*; bucket blocks public access, default encryption on |
Bucket policy changes, other prefixes |
| Secrets | secretsmanager:GetSecretValue on sprintflow/* (AWS) / Key Vault Secrets User on one vault (Azure) / a read-only Vault policy on secret/data/sprintflow/* |
List/write on the whole store |
| PostgreSQL | One database; the role owns only it; TLS (sslmode=require) |
Superuser |
Example IAM policy for Bedrock + S3 + Secrets Manager:
{
"Version": "2012-10-17",
"Statement": [
{"Effect": "Allow", "Action": ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"],
"Resource": ["arn:aws:bedrock:ap-south-1:<account>:inference-profile/apac.anthropic.claude-*",
"arn:aws:bedrock:ap-south-1::foundation-model/anthropic.claude-*"]},
{"Effect": "Allow", "Action": ["s3:PutObject", "s3:GetObject"], "Resource": "arn:aws:s3:::<bucket>/sprintflow/*"},
{"Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::<bucket>",
"Condition": {"StringLike": {"s3:prefix": "sprintflow/*"}}},
{"Effect": "Allow", "Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:ap-south-1:<account>:secret:sprintflow/*"}
]
}
Threat model (summary)#
| Threat | Controls |
|---|---|
| Ticket text or repository content tries to steer the agent (prompt injection) | Draft PRs only โ no merge, approve or mark-ready code exists; independent review; risk approvals; build/test in containers with no network; commands from repository settings are never executed |
| AI-written code runs during build/test | Throwaway container, non-root, all capabilities dropped, CPU/memory limits, no network; fails closed if the runtime is missing |
| Personal data or secrets reach the model | Data guard redaction (reversible placeholders), withheld files, Bedrock in-region |
| Stolen console session / CSRF / XSS | HttpOnly+Secure+SameSite cookies, CSRF token, strict CSP, no inline script, all untrusted text rendered as text; SSO with group-based roles |
| Forged webhooks | GitHub HMAC-SHA256, GitLab secret token, Jira token โ constant-time compared; stop switch honoured |
| Secrets at rest | Encrypted in the console store (Fernet, key from a secrets manager); masked in the API; never logged |
| Hostile test reports / archives | defusedxml (no DTDs/entities); backups checksum-verified, traversal and links rejected |
| Runaway cost | Per-run caps, daily/monthly budgets, alerts, stop switch |
| Losing track of what happened | Audit log (users, changes, runs), per-run event log, OpenTelemetry traces |
Penetration-test checklist#
- Console: authentication (lockout, SSO state/nonce/audience), authorisation (every role against every endpoint), CSRF, XSS in run content, path traversal in artifact URLs, security headers, TLS at the ingress.
- Webhooks: unsigned/forged/replayed requests; oversized payloads.
- Workers: container escape attempts from a malicious test; network egress during build/test.
- Data guard: seeded personal data in tickets and files never appears in model requests (OpenTelemetry/Langfuse).
- Backups: tampered archive, traversal entries, restore without the master key.
AI SprintFlow 1.0.5 ยท Questions? Contact us