Security overview
Effective [date of publication]
| App | TuneCraft: Automation & Site Cleanup, a Jira Cloud app built on Atlassian Forge |
|---|---|
| Marketplace listing | Not listed yet. TuneCraft is not on the Atlassian Marketplace yet, and its app key will be added here when it is. |
| Forge app ID | ari:cloud:ecosystem::app/facece90-dfd5-4792-9bff-6a5bd061a341 |
| Vendor | Plugincraft Software Inc., a company incorporated under the laws of Québec, Canada |
The short version
- TuneCraft runs entirely on Atlassian Forge. It declares no outside network access, so your data does not leave Atlassian.
- Jira decides who may do what in Jira. The app's pages read and change Jira with the person's own Jira rights. A change to your Jira configuration is made only when a Jira admin confirms it, and the clean-up tools are for Jira admins only. The work items the app creates are owner notices, sent by a person at the Manage level as themselves; the work items of the To do page, created as the Jira admin who confirms them; and alerts, which the app creates as itself.
- To report a vulnerability, follow the Vulnerability Disclosure Policy and write to info@plugincraft.ca.
- We respond to Atlassian's security alerts within 8 business hours and to critical support requests within 24 hours, and we fix vulnerabilities within the deadlines of Atlassian's Security Bug Fix Policy for Marketplace apps.
- No penetration test has been done yet. We plan one, and a bug bounty, after the app is listed on the Atlassian Marketplace.
Report a vulnerability
If you think you found a security problem in TuneCraft, follow our Vulnerability Disclosure Policy. It says how to report, what is in scope, how we protect researchers who act in good faith, and what to expect from us and when.
- Write to info@plugincraft.ca. Use sample data.
- For an urgent matter, such as data being exposed now, put "URGENT" at the start of the subject line.
- Security contact hours: 8:00 to 17:00 Eastern Time, Monday to Friday.
Once TuneCraft is listed on the Atlassian Marketplace, you can also report through Atlassian: the Marketplace Security Bug Bounty program and the Vulnerability Disclosure Program.
Response commitments
These are the times Plugincraft commits to. They match the minimums that Atlassian sets for Marketplace partners in the Atlassian Enterprise Certified program, or improve on them. Business days are Monday to Friday, and business hours are the security contact hours: 8:00 to 17:00 Eastern Time. A message that arrives outside business hours counts from the start of the next business period.
| What | Commitment |
|---|---|
| A security alert from Atlassian | We respond within 8 business hours. |
| A critical support request (Severity 1 or 2, see Incident Response) | First response within 24 hours, five business days a week. |
| A vulnerability report from anyone else | Acknowledged within 2 business days. |
| A security incident that affects customers | We notify Atlassian within 24 hours of learning of it. |
| A vulnerability fix | Within the deadlines in the next section. |
Security reports go to info@plugincraft.ca, which receives mail at all times and is read on every business day.
Bug fix deadlines
We rate a vulnerability with its CVSS score and fix it within the deadline in Atlassian's Security Bug Fix Policy for cloud apps. The deadline runs from the day we receive the report, or from the day Atlassian reports the vulnerability to us through the Marketplace, whichever comes first. We checked the policy on October 27, 2026. Atlassian may change it, and the policy on Atlassian's site is the one that applies.
| Severity | CVSS score | Fix deadline |
|---|---|---|
| Critical | 9.0 or higher | 10 days |
| High | 7.0 to 8.9 | 4 weeks |
| Medium | 4.0 to 6.9 | 12 weeks |
| Low | Below 4.0 | 25 weeks |
These are the deadlines Plugincraft commits to. We do not ask for longer ones. Atlassian's policy allows an extension only in limited cases, for example when the fix depends on a change to the Atlassian platform. If we ever need one, we say so to the reporter. A security incident also has a severity and targets in Incident Response. Where both apply, we meet the shorter time.
Security practices
This section describes how we build, run and check TuneCraft. What it says about the app comes from the app's source code and documentation. What it says about Atlassian's platform comes from Atlassian's documentation, linked where it is used.
Secure development lifecycle
- Private source, pull requests only. The source code is private. Every change is made on its own branch and reaches the main branch only through a pull request. Nobody commits to the main branch directly.
- Independent review. Every pull request is reviewed by a reviewer who did not write it. The reviewer is an AI review agent working to written rules (see the AI Usage Policy). It reads the change against those rules, checks that the automated tests pass, and records its verdict on the pull request. Authors never merge their own pull requests.
- Automated tests on every change. On every pull request and every push to the main branch, the build runs type checking, unit tests that must cover at least 90% of lines, branches, functions and statements, a production build, and end-to-end tests of the user interface in a real browser. A feature that people can see ships with its end-to-end tests in the same pull request.
- Tests that guard the promises on this page. One test fails the build if the app declares outside network access, remotes or Connect modules, or any web trigger that does not answer with fixed replies. One fails it if code logs anything but ids, counts and the app's own names. One fails it if a column that holds an account id is missing from the list that erasing and reporting use. One protects released database migrations, which can only be added to, never edited or removed. One fails it if a text is missing in any of the app's eight languages.
- Secret scanning. A scan for secrets runs on every pull request and every push to the main branch. It reads the code and the history behind the commit being tested, with the scanner's default rules.
- Dependency and static analysis scanning. These are not part of the automated checks yet. The app's server code has four runtime dependencies, all of them Atlassian's own Forge libraries.
- Releases. Only people the owner has given access to the app can deploy it.
- Current runtime. The app runs on the Forge Node.js 22 runtime.
Access control
- Who can open the app. Jira admins always can. The groups they allow can use the global view, and a project's admins can use the project view for that project unless Jira admins turn it off. The clean-up tools are for Jira admins only. Every page and every request is checked on the server, and a check that cannot finish refuses the request.
- Jira decides who sees and changes what in Jira. The app's pages read and change Jira with the person's own Jira rights, so Jira applies that person's permissions. Allowing a group in TuneCraft lets its members open the app's pages. It changes nobody's rights in Jira.
- Changes to your Jira configuration need a Jira admin's confirmation. A change in a clean-up tool is made as the Jira admin who confirms it, so Jira's audit log shows that admin. Where Jira has a trash or an archive the app uses it, and it keeps a record of each change with an undo where Jira allows one. The app also creates work items. An owner notice is created as the person who sends it, who needs the Manage level (a Jira admin, or a member of a group a Jira admin allowed at that level). An alert is created by the app's own checks, as the app, in the project and work item type a Jira admin picked; alerts are the only Jira writes the app makes as itself.
- The background checks read as the app, and read configuration only. Once a Jira admin turns a tool's background checks on, the app reads the site's configuration and counts as itself, in the background, within a budget of Jira points. As the app, it reads no work item. Where the app may not read something itself, the page of a Jira admin reads it, as that admin. That includes work items in two tools: Attachments searches the work items that have attachments, in the spaces the admin picks or across the site, and compares file names in memory without keeping them; Archiving searches work items by a filter or a JQL text the admin gives, and changes them only when the admin confirms.
- One web trigger, for the automatic scan. A Jira admin can make a key for the automatic scan. The key is shown once. It has two parts: a secret, of which the app keeps only a one-way hash made with a secret held in an encrypted Forge variable, and the site's scan key, which the sender needs to make the same keyed hashes as the browser. The web trigger accepts a push only with the secret, checks the licence, the size, the order and the hash of each part, and refuses any flow that is not redacted, keeping nothing of that push. It answers with fixed replies only, takes at most 6 pushes a day for a site and refuses more than two open at once. Replacing or turning off the key stops the old secret at once; the scan key does not change. Whoever holds the whole key can push scans to the app and test guesses against a keyed hash, so keep it as you keep the API token, in the sender's secret store.
- Least privilege. The scopes the app asks for, and why, are listed below. Adding one makes a major version that every site admin must approve.
- No credentials. The app asks for no password or Atlassian API token and keeps none. The automatic scan's sender uses the customer's own Atlassian API token to read the rules; the token is never sent to the app. The one secret the app checks is the automatic scan's key, kept only as a one-way hash (see above).
Data minimisation
- The texts of your flows stay out. The browser (or the customer's sender) replaces every text in a flow's settings with a placeholder before anything is sent: JQL, web addresses and headers, email addresses, smart values, custom field names, values compared, comments and secrets. The server stores a flow only so redacted, checks it again, and refuses one that is not. A flow's JQL goes only to your own site's Jira, as the person, to be checked and counted; the app keeps the counts. If a customer uses the automatic scan, its sender first reads the rules' real text through Atlassian's API, with the customer's own token and wherever the customer runs it, which may be ScriptRunner Cloud, a script app from another publisher (see the privacy policy).
- Ids, counts and hashes, not names. From Jira's configuration the app keeps ids, counts, days, Jira's own vocabulary and keyed hashes. The pages read names from Jira, with the person's own rights, when they show them. The texts people wrote that the app keeps are flow names, what a Jira admin types as a setting (such as naming conventions, targets and guidance for checks), and the old and new label of a label change for 30 days.
- Ids, not people. The app stores Atlassian account ids. It stores no names or email addresses; it asks Jira for them when it shows them. It reports the ids it keeps to Atlassian and erases those of closed accounts.
- Logs without content. App logs hold ids, counts, statuses and error codes. See Data Logging.
- Support bundle on request. A support bundle holds versions, the licence state, table sizes and counts. An admin can see the whole file before deciding whether to send it.
- No tracking. The app uses no analytics service. This website uses no analytics and sets no cookies.
Runs on Atlassian (no egress)
- The app declares no external fetch permissions, remotes or Connect modules, and it uses no outside scripts, fonts, images, analytics or logging services. A test fails the build if any is added. Its one web trigger answers with fixed replies. It is built to stay eligible for Atlassian's Runs on Atlassian program.
- Plugincraft has no servers of its own. The only subprocessor of app data is Atlassian (see Subprocessors), and all the data the app stores stays in your Jira site's data residency location.
- Atlassian states that the Forge platform is SOC 2 attested and ISO 27001 certified, and that an app that uses Forge's runtime and hosted storage and has no data egress can rely on the controls it inherits from the platform. That covers the platform. It is not a certification of Plugincraft. Atlassian also says that when an app runs entirely on its platform, it can fully support investigation, containment and log sharing during an incident.
Encryption at rest and in transit
- At rest. TuneCraft stores customer data only in Forge SQL, Atlassian's hosted database for Forge apps. It keeps nothing on a server of its own. Atlassian states that the Forge platform uses AES-256 to encrypt data at rest for data stored within Forge app storage. Forge SQL is Forge hosted storage, covered by the same Forge data lifecycle documentation.
- In transit. Atlassian states that the Forge platform uses TLS 1.2 or higher to encrypt data in transit. The app makes no other connections. This website redirects plain HTTP to HTTPS and tells browsers to use HTTPS only.
- Secrets. The app keeps no password or API token. The one secret of its own, used to make the one-way hash of the automatic scan's key, is an encrypted Forge variable. The key itself is shown once to the Jira admin who makes it; the app keeps its hash, and the site's scan key beside the rest of its data.
Backups and recovery
- Atlassian backs up the storage. Atlassian states that databases provisioned and managed through Forge SQL are backed up periodically, and that the Atlassian cloud backs up all persistent Forge storage for disaster recovery. If an app deletes data by mistake, Atlassian can restore it when a support ticket is raised within 21 days of the deletion.
- Plugincraft holds no copy. We keep no copy or backup of customer data. The app's code is in a private source repository, and a new version can be deployed to Forge from it.
- Record files, not backups. Before it deletes something Jira cannot restore, such as a status, a workflow or a project role, the app gives the Jira admin a record file of what it holds, to save on their own computer. Plugincraft never receives it. The app has no backup and restore of its own data.
- If something fails. How we keep the app running and recover from each kind of disruption is in Business Continuity and Disaster Recovery.
Penetration test and bug bounty (planned)
- Penetration test. No penetration test of TuneCraft has been done yet. After the app is listed on the Atlassian Marketplace, we plan to have it tested once a year, through Atlassian's penetration test program or by a CREST-accredited provider. Once a test is done, we plan to make the report or an attestation letter available to customers under a non-disclosure agreement.
- Bug bounty. TuneCraft is not yet in a bug bounty program, and Plugincraft pays no rewards for reports yet. After the app is listed, we plan to take part in Atlassian's Marketplace Security Bug Bounty program.
- None of this has been done yet. We will update this page when a test is done or the program is joined.
Permissions the app asks for
These are the 65 Forge scopes in the app's manifest, and what each is for. Each Jira admin who installs the app approves them. The app asks for the fewest it needs.
| Scope | What it is for |
|---|---|
| read:jira-work | Check, as the person, whether they are a Jira admin or a project admin. Count, as the person, the work items a scheduled flow's search finds now (Jira's approximate count), and have Jira check a flow's JQL. Have Jira check, from the Optimize page, the Jira expression of a validator that Optimize proposes, and read the names of the statuses a flow names by id, as the person. Read the site's configuration that flows name, as the app or as a Jira admin; the Limits tool's reports of work items near Jira's caps, as the admin who opens the page (shown to them, never stored); the work items that have attachments, for the Attachments tool, and the work items an Archiving search finds, as the Jira admin who uses the tool (the ids of the largest are kept, never a name or a text); the site's labels, the count of work items that carry each and a search for the work items that carry a label picked, for the Labels tool, as the Jira admin who has it open; the count of the open work items of a sprint, for Sprints left behind, as the Jira admin who has it open; the status of the work item linked to a To do action; and the fields a work item type requires. Counts are kept; work item content is not. |
| write:jira-work | Create Jira work items: a notice to a flow's owner, as the person who sends it; the actions the To do page creates, as the Jira admin who confirms; the alerts, as the app (the only Jira writes the app makes as itself), in the project and work item type a Jira admin picked. Also, as the Jira admin who confirms (a filter, as its owner): a new owner or name for a filter or dashboard, each with an undo; the deletion of a filter or dashboard, which has none; a filter's JQL written again with a field's id in place of a name Jira no longer accepts, as its owner, when that owner is the person confirming (taking a filter from its owner to repair it is not offered yet), with an undo; sharing taken out for anyone on the web, every signed-in person or a space Jira no longer shows, on many filters and dashboards at once, with an undo; the Archiving tool's archiving of old work items, which its undo restores, and its move of stale work items to another status, which has no undo; the Labels tool's rename, merge and removal of a label on the work items that carry it, one at a time and without Jira's notification emails, with an undo for 30 days; the Merge fields page's copy of one custom field's values into another of the same type, on the work items that have one, only where the second is empty, one work item at a time and without Jira's notification emails, with an undo that clears the second field only where it still equals the first; and the Attachments tool's deletion of attachments, which Jira cannot bring back and which has no undo. |
| read:jira-user, read:user:jira, read:group:jira, read:avatar:jira | Learn who the person is and which groups they belong to; look up groups and people by name; show the names of flow owners as Jira shows them; check whether the accounts that flows name are still active; and, on the Groups page, read the first members of the groups a permission scheme grants something to, and group names. Names are shown and not stored. |
| write:group:jira | Remove deactivated people from a group, and add them back on undo, as the Jira admin who confirms. TuneCraft never deactivates or deletes an account. |
| storage:app | Forge hosted storage (Forge SQL) for the app's own data. |
| report:personal-data | Report the Atlassian account ids the app stores, once for each reporting cycle, and learn which accounts were closed so their data can be erased. |
| read:license:jira | Read, as a Jira admin, whether the site's Jira plan is Free and Jira's approximate count of its users, so admins need not type them. |
| read:issue-type-scheme:jira | Read which work type schemes hold each work type and which spaces use each scheme (ids and the default flag). Read only. |
| read:workflow:jira, read:workflow-scheme:jira, read:status:jira | Read workflows with the keys of the rules on their transitions, statuses, and the workflow schemes that hold each workflow with the number of spaces using them, to find workflows and statuses no space uses. Read only. A rule's settings are not kept. |
| write:workflow:jira, delete:workflow:jira, delete:workflow-scheme:jira | Delete a status, a workflow or a workflow scheme that nothing uses, as the Jira admin who confirms, after a record file they save. Jira has no trash for these. |
| read:project:jira, read:project-category:jira, read:project.property:jira, read:project-version:jira, read:project.component:jira, read:issue-type:jira, read:issue-type-hierarchy:jira | Read spaces, their categories, versions and components, and work types, for the Spaces, Schemes and Workflows tools and for the calls below. Jira's own sets for these calls list several of them together. The Spaces tool's weekly reading also asks for each space's lead, and keeps the lead's account id only while Jira says the lead is inactive; the app reads no role through them. |
| write:project:jira, delete:project:jira, write:project.avatar:jira, write:project-version:jira, delete:project-version:jira, delete:project.component:jira | Archive, put in Jira's trash or restore a space; change its lead, default assignee and category; put spaces on another permission scheme when identical schemes are merged (an undo puts them back); release, archive or delete a version; and delete a component, as the Jira admin who confirms, with an undo where Jira allows one. |
| read:screen:jira, read:screen-tab:jira, read:screenable-field:jira, read:screen-scheme:jira, read:issue-type-screen-scheme:jira, read:field-configuration:jira, read:field-configuration-scheme:jira, read:notification-scheme:jira, read:issue-security-scheme:jira, read:issue-security-level:jira | Read screens, their tabs and fields, field configurations, schemes and what uses each, to find those nothing uses and to count what a screen or a notification scheme holds, and, for Sprints left behind, to tell whether a space has issue security levels. Read only. Ids and counts are kept, never names. |
| read:field:jira, read:custom-field-contextual-configuration:jira, read:field.option:jira | Read fields, where a custom field is used (its contexts, spaces, screens and tabs) and whether a context holds an option. Read only. Ids, counts and true or false are kept. |
| write:field:jira, delete:field:jira | Move a custom field to Jira's trash, restore it, and delete a field that is already in the trash; and add spaces to a context of the field to keep in a merge (an undo takes them off), as the Jira admin who confirms. |
| write:field.option:jira | Disable or enable the options of a select field's context, and create in the field to keep in a merge the options it lacks (an undo disables them), as the Jira admin who confirms. TuneCraft never deletes an option. |
| write:issue-type-screen-scheme:jira, delete:issue-type-screen-scheme:jira | Put the spaces of a copy of a work type screen scheme on the identical scheme the admin keeps, and delete the copy that is left empty, as the Jira admin who confirms, after a record file they save. The schemes are proved identical again before each call. A move has an undo; Jira does not give a deleted scheme back. |
| write:screenable-field:jira, delete:screenable-field:jira | Add the field to keep in a merge to the tab of each screen that shows the field to empty, right after it, and, for the undo, take it off only the screens TuneCraft added it to, as the Jira admin who confirms. Never a work item. |
| read:project-role:jira, read:application-role:jira, read:permission:jira, read:permission-scheme:jira | Read project roles, permission schemes and their grants to groups, roles and people, and the roles of each space, to find roles and groups nothing uses and deactivated people a scheme still names. |
| delete:project-role:jira | Delete a project role that no permission scheme grants and no space gave actors, as the Jira admin who confirms, after a record file they save. |
| write:permission:jira, delete:permission:jira | Take a role's grants out of the permission schemes in which no space that uses the scheme gives the role actors, and add them back on undo. Also take out a grant that gives a permission to anyone or to every user of a product, or give it to a group or a role instead, and put it back on undo. All as the Jira admin who confirms. TuneCraft never changes who is in a role. |
| delete:permission-scheme:jira | Delete a permission scheme copy that no space uses after its spaces were put on an identical scheme, as the Jira admin who confirms. |
| read:board-scope:jira-software, read:board-scope.admin:jira-software, read:sprint:jira-software | Read, as the Jira admin who opens Boards or Sprints, the boards, their configuration and filter, and the sprints. Shown to them, never stored. |
| write:sprint:jira-software, delete:sprint:jira-software, write:board-scope:jira-software | Rename, close and delete sprints, add the open work items of a sprint it closes to the next future sprint or to a new one, and delete orphaned boards, as the Jira admin who confirms. Closing a sprint and deleting one have no undo. Names are not stored; the record keeps ids, states and keyed hashes. |
| read:audit-log:jira | Read Jira's audit records, only when a Jira admin presses "Who did it" on the Change history page, as that admin, for the days they picked. Shown to them and never stored. |
Incidents and status
How we handle an incident is in Incident Response. A status page will be published with the Marketplace listing. Problems with Jira or Forge themselves are reported on Atlassian's status page.