Developer
News and Updates
Get Support
Sign in
Get Support
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Last updated Feb 19, 2026

Security guidelines for Atlassian Government Cloud (AGC) apps

These guidelines are designed to help developers build secure AGC apps by following best practices aligned with FedRAMP controls and Atlassian's security standards. We strongly recommend following these guidelines to protect customer data and maintain their trust.

For mandatory requirements, refer to Security requirements for Atlassian Government Cloud apps. For more information on FedRAMP compliance, refer to Security and compliance on the AGC.

Authentication and authorization

Use Forge OAuth 2.0

All AGC compatible apps must use Forge's built-in OAuth 2.0 implementation for authentication and authorization with Atlassian APIs. This ensures secure, standardized authentication flows that align with security requirements.

Best practices:

  • Use Forge's built-in methods for authentication and authorization with Product APIs instead of less secure methods like basic auth
  • Do not expose unauthenticated web triggers or remote hosts that can be accessible from the internet
  • Always validate user permissions before using asApp() or appSystemToken methods for actions triggered in user context. These authorization methods possess app-level permissions and elevate privileges, unlike asUser(), which enforces user permissions

Example: Using Forge authentication APIs

1
2
import api, { fetch } from '@forge/api';

// Correct: Use Forge's authenticated request method asUser()
// This automatically handles OAuth 2.0 authentication on behalf of the user
const response = await api.asUser().requestJira('/rest/api/3/issue/PROJ-123', {
  method: 'GET',
  headers: {
    'Accept': 'application/json'
  }
});

// Incorrect: Do not use credentialed requests
const badResponse = await fetch('https://api.atlassian.com/ex/jira/rest/api/3/issue/PROJ-123', {
  method: 'GET',
  headers: {
    'Accept': 'application/json',
    'Authorization': 'Basic ' + btoa('user@example.com:api_token') // Never do this - use Forge's auth methods
  }
});

Credential management

Do not collect, use, or store Atlassian account credentials (namely, secrets managed by Atlassian identity). This is strictly prohibited:

  • API Tokens / Personal Access Tokens (PATs)
  • User or admin passwords
  • Admin API keys (including Org/Sys Admin API Tokens)
  • Access/Container tokens (e.g., Bitbucket Cloud access tokens)
  • OAuth credentials (client secrets)

Data security

Tenant isolation

Ensure strict tenant isolation at runtime. Each tenant's data must be completely isolated from other tenants.

Implementation guidelines:

  • Use Forge's tenant context to isolate data access
  • Do not store customer data or variables in global, static, or shared memory spaces (including in-memory caches) that could be accessed by other customers' tenants
  • Do not share runtime artifacts or variables between customer tenants
  • Use Forge storage APIs that automatically enforce tenant isolation

Example: Tenant-isolated storage

1
2
import { kvs } from '@forge/kvs';

// Correct: Forge storage automatically enforces tenant isolation
await kvs.set('customer-data', data); // Isolated per tenant

// Incorrect: Use global variables or shared state
global.sharedCache = {}; // Never do this - violates tenant isolation

Failure to maintain isolation could result in accidental data leakage or unauthorized access, leading to a loss of customer trust.

Arbitrary code execution

Do not execute arbitrary code or spawn external processes. All code execution must be securely sandboxed.

Best practices:

  • Do not execute arbitrary code directly from user input: Do not use functions such as eval(), Function(), exec(), spawn(), fork(), or similar APIs that interpret or execute code provided by users or external sources
  • Prohibit process spawning: Your app must not use Node.js child_process APIs (e.g., spawn, exec, fork, execFile) or equivalent APIs to launch new processes, run shell commands, or invoke system binaries
  • Sandbox any permitted code execution: If your app must execute code (e.g., for templating, scripting), use a secure, restricted sandbox component that isolates execution per tenant/customer to prevent cross-tenant data leakage

Example: Avoiding dangerous code execution

1
2
// Never do this - executes arbitrary code
const userInput = req.body.code;
eval(userInput);

// Never do this - spawns external processes
const { exec } = require('child_process');
exec(userInput, (error, stdout, stderr) => {
});

Allowing apps to spawn new processes or execute arbitrary code, especially code derived from user input introduces significant security risks, including remote code execution that compromises the app's runtime environment.

Network security

Explicitly list all egress domains in your Forge manifest. Do not use wildcard entries.

Implementation:

1
2
# Correct: Explicitly list all egress domains
permissions:
  external:
    fetch:
      backend:
        - 'https://api.example.com'
        - 'https://secure.example.com'

What to avoid:

1
2
# Never do this - wildcard is prohibited
permissions:
  external:
    fetch:
      backend:
        - '*'  # Wildcard is prohibited
        - '*.com'  # Wildcard patterns are also prohibited

It is critical to tightly control which external domains your app can communicate with. The Forge manifest file (manifest.yml) defines the set of domains your app is permitted to access for outbound (egress) network requests. Allowing unrestricted or overly broad network access such as by specifying a wildcard (*) for egress domains poses significant security risks, including the potential for data exfiltration, command-and-control attacks, or abuse of your app as a proxy for malicious activity.

Application security

Content Security Policy (CSP)

Do not use unsafe-inline or unsafe-eval in your CSP directives when possible. These weaken your app's security posture and can lead to injection attacks.

Best practices:

  • Use hash-based (<sha-algorithm>-<base64-value>) sources for inline scripts
  • Avoid eval() and similar dynamic code execution
  • Avoid broad CSP directives in your Forge manifest

Understanding CSP risks:

  • unsafe-inline allows browsers to execute any inline JavaScript code (such as <script>...</script> blocks or onclick attributes) directly in the HTML. This makes it much easier for attackers to inject malicious scripts if they can control any part of your custom UI implementation.
  • unsafe-eval allows the use of JavaScript functions like eval(), new Function(), or setTimeout(), which can execute arbitrary code. Attackers can exploit this to run harmful scripts if they find a way to inject code.

Example: Insecure CSP configuration

1
2
# Incorrect: Using unsafe directives
app:
  id: ari:cloud:ecosystem::app/your-app-id
  runtime:
    name: nodejsx.x
  permissions:
    content:
      scripts:
        - "unsafe-inline"
        - "unsafe-eval"

Secure coding practices

Secure coding is a foundational requirement for building trustworthy Forge apps, especially for Atlassian Government Cloud (AGC) compatibility. Developers should follow Atlassian's XSS prevention guidelines and understand OWASP Top 10 issues to prevent common vulnerabilities and ensure robust protection of customer data.

Forge Custom UI apps:

Forge Custom UI apps allow you to build custom interfaces using HTML, CSS, and JavaScript. These apps require additional security considerations:

  • You must still validate and sanitize user input
  • Use proper output encoding when rendering user-controlled data

Best practices:

  • Always validate all user-supplied data at the point of receipt, including data from HTTP requests, webhooks, and integrations
  • Do not trust input from users or external systems
  • Reject or sanitize any unexpected or malformed input
  • Encode all output that is rendered in the UI or sent to external systems to prevent injection attacks (e.g., Cross-Site Scripting/XSS)
  • Use context-appropriate encoding (HTML, JavaScript, URL, etc.)
  • Avoid directly inserting user input into templates or responses
  • For Custom UI apps, use safe DOM manipulation methods (e.g., innerText instead of innerHTML)

Example: Input validation and sanitization

If you're building a Custom UI app and need to handle user-defined HTML content, use DOMPurify:

1
2
import DOMPurify from 'dompurify';

// Correct: Validate and sanitize user input
function processUserInput(userInput) {
  // Validate input type and length
  if (typeof userInput !== 'string' || userInput.length > 100) {
    throw new Error('Invalid input');
  }
  
  // Sanitize HTML content using DOMPurify
  const sanitized = DOMPurify.sanitize(userInput, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p'],
    ALLOWED_ATTR: []
  });
  
  return sanitized;
}

// Incorrect: Directly using user input
function badProcessUserInput(userInput) {
  // XSS vulnerability
  document.getElementById('output').innerHTML = userInput;
}

// Correct: Use safe DOM methods
function safeProcessUserInput(userInput) {
  // innerText automatically escapes HTML
  document.getElementById('output').innerText = userInput;
}

If you use DOMPurify or other HTML sanitization libraries, you must regularly patch them. Browsers change functionality and bypasses are discovered regularly. See Atlassian's XSS prevention guide for more information.

Data encryption

Transport security

All outbound connections must use HTTPS with TLS 1.2 or higher.

Best practices:

Encryption-at-rest

For apps that egress data, implement strong encryption at rest.

Best practices:

Using Forge encrypted storage:

For sensitive information such as API keys, passwords, tokens, or PII, use the encrypted storage API from @forge/kvs:

1
2
import { kvs } from '@forge/kvs';

// Correct: Store secrets using Forge encrypted storage
await kvs.setSecret('third-party-api-key', apiKey);

// Retrieve encrypted secret
const apiKey = await kvs.getSecret('third-party-api-key');

// Incorrect: Never hardcode secrets
const apiKey = 'sk_live_1234567890abcdef'; // Never do this

// Incorrect: Using regular storage for secrets
import { kvs } from '@forge/kvs';
await kvs.set('third-party-api-key', apiKey); // Not encrypted!

Data privacy

Principle of least privilege

Request only the minimum scopes and permissions necessary for your app's functionality.

Best practices:

  • Apps should request only the minimum necessary permissions required for the functionality
  • Overly broad permissions raise the risk profile and potential impact of a compromise
  • Remove any unnecessary permissions
  • Document why each scope is required and provide justification in Privacy & Security tab questionnaire

Third-party integrations disclosure

Clearly disclose all third-party integrations and data handling practices.

Required disclosures:

  • For apps that egress data to remote hosts or external domains, clearly disclose all third-party integrations that may receive, process, or store customer data
  • The names and purposes of all third-party services or vendors integrated with the app
  • The types of data shared with each third-party integration
  • The data retention and deletion policies that apply to any data egressed from the app must be clearly defined and followed, including how long data is retained and the process for secure deletion
  • Make this information publicly available to customers such as in the app's privacy policy, security documentation, or a dedicated transparency page so customers can make informed decisions about the use of your app and the handling of their data

This information must be made publicly available to customers via the Privacy & Security tab of your Marketplace listing. This transparency is critical for maintaining customer trust and aligning with FedRAMP and Atlassian Government Cloud (AGC) requirements.

Supply chain security

Dependency management

Proper management of third-party dependencies is critical for maintaining the security posture of AGC-compatible apps and aligns with FedRAMP controls.

Best practices:

  • Do not use libraries that have not received updates or security patches in the past 12 months
  • Avoid libraries that have open, unaddressed critical vulnerabilities or have been marked as deprecated by their maintainers
  • Regularly audit your package.json and package-lock.json (or equivalent) files for outdated or insecure packages and Keep dependencies up to date with security patches
  • Avoid the use of unsupported or EOL Node.js versions and deprecated libraries during build and deployment, always review Node.js versions supported by Forge
  • Use dependency scanning tools (e.g., npm audit, Snyk, OWASP Dependency-Check)
  • Prioritize fixing Critical and High severity vulnerabilities as soon as they are discovered

Example: Dependency scanning

1
2
# Correct: Regularly audit dependencies
npm audit

# Fix vulnerabilities automatically where possible
npm audit fix

Open source tools:

Vulnerability management

Vulnerability remediation timelines

Address vulnerabilities according to severity-based timelines as per Security Bug Fix policy:

  • As a best practice, all exploitable vulnerabilities must be prioritized and remediated as soon as discovered regardless of severity

Security scanning

Implement regular automated security scanning. This aligns with FedRAMP's Configuration Management and Vulnerability Management control families, which emphasize continuous identification and mitigation of security weaknesses.

Required scanning:

  • SAST (Static Application Security Testing): Scan source code for vulnerabilities
  • SCA (Software Composition Analysis): Scan third-party dependencies for known CVEs

Integration with CI/CD:

Integrate automated vulnerability scanning tools into your CI/CD pipeline to regularly assess your app's source code and dependencies for security weaknesses. This should include:

Security incident response

If you discover a security incident:

  1. Investigate and immediately contain the incident to reduce the impact
  2. Notify Atlassian via ECOHELP
  3. Assess the severity and impact to customer data
  4. Prioritize remediation and apply security patches immediately
  5. Follow the Security Incident Response Guidelines for guidance and customer notifications.

Secure configuration

Establish and maintain secure configuration baselines for the Forge app, including remote resources and its dependencies, by maintaining an inventory such as a Software Bill of Materials (SBOM). Generate an SBOM automatically during each build or release using tools like cyclonedx-npm or npm, and update it whenever dependencies change to keep an accurate inventory of all components and their versions. Store and version control the SBOM files alongside your code for traceability and security auditing purposes. Regularly review and update these baselines to reflect changes in app functionality or dependencies.

1
2
# Generate SBOM using npm (run from project root)
npm sbom > sbom.json

# Using CycloneDX format (run from project root)
npx @cyclonedx/cyclonedx-npm --output-file sbom.json

# Integrate into CI/CD
# Add to your bitbucket-pipelines.yml or CI workflow

Best practices:

  • Do not hardcode secrets such as API keys, passwords, or other credentials directly into your source code or store them in locations that are easily accessible, such as configuration files checked into version control or public repositories
  • All sensitive information should be securely managed using Forge's encrypted storage API (kvs.setSecret()), not the regular storage API (storage.set())

Security assessment

Conduct regular security testing (manual and automated) to identify low hanging vulnerabilities.

Best practices:

  • Conduct penetration tests at least annually, or after significant changes to app functionality or architecture
  • Penetration testing should simulate real-world attack scenarios, including attempts to bypass authentication, escalate privileges, or access data across tenants

Partner verification

Ensure that you complete all Partner verification steps as outlined in the Marketplace onboarding requirements. This process is essential for confirming your organization's identity and establishing trust with Atlassian and its customers.

Partner verification typically involves validating your business entity and verifying contact information to validate your identity.

Security contact

Designate at least one security contact who:

An admin can also be listed as a security contact. See the vulnerability review practices guide for more information. Once your account is created, add your email address as a security contact by following the instructions in this link.

Rate this page: