How Scripts Run
Most of what you write runs in a restricted Python sandbox. It's a stripped-down Python that can't reach the file system, the network, or the machine it's running on. The only way to reach anything outside the run is through the jira and work_item objects we give you, so a script can only ever do what your Jira permissions already allow.
Every run gets a fresh sandbox process that's thrown away afterwards. One script can't leave anything behind for the next one, and a script that misbehaves is killed without affecting anything else. Limitations lists exactly what the sandbox blocks.
Changes are held back while the script runs and only sent to Jira once it finishes. A script that fails partway through changes nothing. The updates that do go through are reported individually on the Output tab, so you always see what actually happened rather than what was intended.
Two features don't use it
Behaviours don't run in the sandbox. The Python you write is translated into JavaScript when you save it, and that JavaScript runs in the browser on the Jira screen. A behaviour that only reads and changes the fields in front of it sends nothing anywhere while someone fills in a form, which is what keeps the screen responsive. Two things a script can opt into do send data out of the browser: a Jira REST call goes to Jira as the person on the screen, and a log line is stored so an admin can read it back.
Workflow Restrict transition and Validate details rules are translated into a Jira expression when you save them, and Jira evaluates that expression itself. Our backend isn't in the path of a transition, so a rule can't slow one down or block one by failing. Perform actions rules are the exception and run in the sandbox like everything else.
Note: All of this runs inside Atlassian's Forge platform. There's no server of ours anywhere in the picture, and your data never leaves Atlassian's environment.
Permissions and Identity
PyRunner is for Jira administrators. Every page in the app is gated on the Jira administrator permission, so nobody else can open it, write a script, or see what previous runs did.
Every script runs as one of two identities, and you choose which with the Run as setting. PyRunner is the app's own account, which sees everything on the site. Your own account holds the script to your Jira permissions, exactly as if you were clicking through Jira yourself, and puts your name on the changes. The PyRunner User covers the trade-off in full.
Behaviours are the exception, and they have no Run as setting. When a behaviour script calls Jira, the call runs as whoever has the screen open, with their permissions. It can't read anything that person couldn't already see.
Credentials never enter the script. Tokens are held by Atlassian's infrastructure and attached to requests after they leave the sandbox, so a script can't read one, and it can't act as anyone other than the identity it was given.
What we ask for at install
Jira asks you to approve a list of permissions when you install the app. Here's the complete list and why each one is needed.
| Permission | Why we need it | Permission | Why we need it |
|---|---|---|---|
| read:jira-work | Read work items, comments, and worklogs | write:jira-work | Edit fields, comment, transition, and create work items |
| read:jira-user | Look up names and account ids | read:jql:jira | Run the JQL behind searches |
| read:project:jira | List spaces | read:issue-details:jira | Read the work items a sprint search returns |
| read:board-scope:jira-software | jira.boards() | read:sprint:jira-software | jira.sprints() and jira.sprint_work_items() |
| read:group:jira | jira.group_members() | read:project-role:jira | jira.space_roles() |
| read:app-user-token | Run a script as the person who launched it | read:app-system-token | Run a script as the PyRunner user |
| manage:jira-configuration | Receive the admin-side events listeners can subscribe to | manage:jira-project | Required by Jira for behaviours to change a screen |
| storage:app | Store your scripts, your configuration, and run history |
The read and write permissions are broad because a script can ask for anything you can. They're the same permissions you already have as an administrator, not additional reach.
Data Handling
We don't collect your data. There's no analytics, no telemetry, and no reporting of any kind back to us. The app declares no outbound destinations at all, so there's nowhere for your data to go even in principle.
The whole app runs inside Atlassian's Forge platform, and the backend that runs your Python is hosted by Atlassian in the same region as your Jira site. Your data stays inside Atlassian's environment from end to end, and traffic within it is encrypted with TLS.
What's stored is the work you create: your scripts, the configuration of your listeners, jobs, behaviours and scripted fields, and a history of what ran. That sits in Atlassian's storage, scoped to your site. Your Jira data isn't stored. Scripts read it, work with it in memory, and it goes when the run ends.
One thing to know if you write log lines in a behaviour: those lines are stored so an admin can read them back, and whatever the script puts in the message is stored with them. If a message includes a field value from the screen, that value is stored too. Keep anything sensitive out of the text you log.
Run history and output are kept for about a week. Limitations has the exact figures.
PyRunner is covered by our registration with the Cloud Security Alliance (CSA) STAR Level 1 program, which publishes our security practices and controls for you to review.
View our CSA STAR Registry entry →Security Questions?
If you have specific security questions or concerns, our team is here to help.
