Spillproof documentation (source for the public SPDOCS knowledge base)
Getting started
- Install Spillproof from the Marketplace into Confluence. To scan Jira too, add it to Jira on the same site (one subscription covers both).
- Open Confluence settings > Sensitive data scanner (or Jira settings > Apps > Sensitive data scanner). Only admins see these pages.
- From now on, every page, blog post, comment and issue is checked when it is saved.
- On the Scans tab, click Scan Confluence and Scan Jira once to check existing content. Scans run in the background inside Atlassian; you can close the page.
- Review the Findings tab. Start with critical findings (keys, private keys, live payment keys, database passwords).
Where things are
| Place | Who | What |
|---|---|---|
| Confluence settings > Sensitive data scanner | Confluence admins | Findings, scans, detectors, scope, notifications and access, ignored values |
| Jira settings > Apps > Sensitive data scanner | Jira admins | The same page (settings and findings are shared) |
| Apps > Sensitive data | Reviewers chosen by an admin | The findings dashboard |
| "..." > Sensitive data check (any page or issue) | Anyone who can see it | Masked findings for that page or issue, and Scan now |
JQL sensitiveData > 0 | Anyone (count only) | Issues with open findings (if the admin left it on) |
What is scanned
Confluence: page and blog post titles and bodies (including code blocks and link targets), footer and inline comments. Jira: summary, description, environment, text custom fields and all comments.
Not scanned: attachments, Confluence whiteboards and databases, page history, Jira issue history, labels, space descriptions and templates.
When: on create and update (within seconds), by full scans you start, and by a daily catch-up of everything changed since the previous day (this also picks up edited Jira comments, which have no Forge event).
What is detected
Secrets
| Detector | Severity | How it confirms a match |
|---|---|---|
| Private key | critical | PEM or OpenSSH private key blocks (RSA, EC, DSA, OpenSSH, PGP, PKCS#8), only when key material follows the header. |
| AWS access key | critical | AWS access key IDs (AKIA, ASIA) and, when one is nearby or labelled, the 40-character secret access key. |
| GitHub token | critical | GitHub personal, OAuth, app and refresh tokens (ghp_, gho_, ghu_, ghs_, ghr_, github_pat_). The built-in CRC32 checksum is verified. |
| GitLab token | critical | GitLab personal, project, group, deploy and runner tokens (glpat-, gldt-, glrt-, GR1348941). |
| Slack token or webhook | high | Slack bot, user, app and refresh tokens (xoxb-, xoxp-, xapp-) and incoming webhook URLs. |
| Stripe live key | critical | Stripe live secret and restricted keys (sk_live_, rk_live_). Test-mode keys are ignored unless test data is included. |
| Google API key or service account | high | Google Cloud / Firebase API keys (AIza...) and service-account JSON with a private key. |
| OpenAI or Anthropic API key | critical | OpenAI keys (identified by their embedded T3BlbkFJ marker) and Anthropic keys (sk-ant-api03-, sk-ant-admin01-). |
| Atlassian API token | critical | Atlassian account API tokens (ATATT3...) and Bitbucket app passwords labelled as such. |
| Package registry token | high | npm (npm_, checksum verified), PyPI (pypi-AgEI...), Docker Hub (dckr_pat_) and NuGet (oy2...) tokens. |
| Email and SMS provider key | high | SendGrid (SG.x.y), Mailgun (key-...) when labelled, Twilio API key SIDs with a secret nearby. |
| Azure storage or connection string | critical | Azure Storage account keys and Service Bus / Event Hubs shared access keys inside connection strings. |
| Database URL with password | critical | postgres://, mysql://, mongodb://, redis://, amqp:// and similar URLs that include a real-looking password. |
| JSON Web Token | medium | Signed JWTs (three base64url parts whose header decodes to JSON with an "alg"). Session tokens pasted from browser tools are a common leak. |
| Password or secret in plain text | high | Labelled credentials such as "password: ...", api_key = "...", client_secret=... where the value looks real (not a placeholder, mixed characters, or high entropy). |
Financial
| Detector | Severity | How it confirms a match |
|---|---|---|
| Payment card number | high | Card numbers that pass the Luhn checksum and match a real issuer range and length (Visa, Mastercard, Amex, Discover, JCB, Diners, UnionPay, Maestro). Phone numbers, order numbers, published test cards and evenly repeated digits are skipped. |
| Bank account (IBAN) | medium | International Bank Account Numbers that pass the ISO 7064 mod 97 check and have the right length for their country. Documentation examples are skipped. |
| US bank account with routing number | medium | An ABA routing number that passes its checksum, labelled as routing/ABA, next to a labelled account number. |
Identity
| Detector | Severity | How it confirms a match |
|---|---|---|
| US Social Security number | high | SSNs written as 123-45-6789 that follow SSA numbering rules, or 9 digits right after "SSN" / "social security". |
| UK National Insurance number | high | National Insurance numbers (AB 12 34 56 C) that follow HMRC prefix rules. |
| Canadian Social Insurance number | high | SINs that pass the Luhn check, only when labelled "SIN" or "social insurance". |
| Passport number | high | Passport numbers only when labelled "passport no." / "passport number", plus machine-readable passport lines (MRZ) with valid check digits. |
Contact details (off by default)
| Detector | Severity | How it confirms a match |
|---|---|---|
| Email address | low | Email addresses outside your own domains. Off by default: Jira and Confluence are full of colleagues' addresses. |
| Phone number | low | International (+country code) and labelled phone numbers. Off by default. |
Custom patterns: add your own regular expressions on the Detectors tab (for example
EMP-(\d{6}) for employee IDs). If the pattern has a group in brackets, only the group is the
sensitive value. Patterns that nest repeats, like (a+)+, are refused because they can hang.
Confidence
- Verified: a checksum or provider-specific marker proved it (Luhn + issuer, mod 97, CRC32,
T3BlbkFJin OpenAI keys, a JWT header that decodes). - Likely: a strong format plus structure rules.
- Possible: labelled values like
password: ...that pass the strength rules.
Settings > Detectors > Accuracy lets you report only verified, likely-and-verified, or everything. Published test card numbers, documentation IBANs and Stripe test keys are skipped unless you include test data.
Fixing findings
| Action | What happens |
|---|---|
| Redact | Replaces the value in the current page, comment or issue field with [redacted <type>], as you (you need edit permission). Old versions stay in Confluence page history and Jira's History tab. |
| Restrict page | Confluence only: view and edit restricted to you and the page author. Remove it from the page's lock icon later. |
| Rotated / Fixed | Closes the finding. Use Rotated for keys and passwords you have revoked. |
| Not sensitive | Closes it and ignores this exact value everywhere (by fingerprint). Undo under Ignored values or with Reopen. |
| Reopen | Opens it again and stops ignoring the value. |
Findings also close by themselves when the value is removed, or the page or issue is deleted.
For passwords, keys and tokens, rotate them. Anyone who saw the page, an email notification, an export or the history may have the old value. Redacting the text is not enough.
Notifications and access
- Reviewers: people who can see the Apps > Sensitive data dashboard without being admins.
- Email the author (Jira): the reporter or comment author gets a Jira email with the masked finding and a request to remove it.
- Weekly digest: new findings and open totals, masked. Either a Jira email sent from an issue you pick (choose an issue in a project only your reviewers can see), or a Confluence page you pick that the app rewrites each week (restrict the page; its watchers get the email).
- JQL property:
sensitiveData > 0finds issues with open findings. Stores only the count. - Label: an optional label added while an issue has open findings and removed after.
Privacy
Spillproof runs entirely on Atlassian's Forge platform (Runs on Atlassian). It sends nothing outside Atlassian and uses no AI service. It never stores a found value: only a masked preview (for example "Visa ending 4242") and a keyed fingerprint (HMAC-SHA256 with a random key created for your site) so it can recognise the same value again. CSV exports contain masked values only. Full privacy policy: https://greatwork.company/apps/spillproof/privacy