> For the complete documentation index, see [llms.txt](https://docs.nullify.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nullify.ai/enterprise-tier/azure-install.md).

# Azure DevOps Install

### Install Guide for Azure DevOps

{% hint style="warning" %}
Azure DevOps is enabled per tenant. If **Connect Azure DevOps** isn't visible in your dashboard yet, contact your Nullify representative to have it turned on for your tenant first.
{% endhint %}

Nullify connects to Azure DevOps Services (cloud) through Microsoft sign-in and any consent your directory requires. You do not create an app registration, supply a client secret, or configure webhooks manually. Azure DevOps Server and bring-your-own service principal connections are [not yet supported](#not-yet-supported).

### Before connecting

* If your company has a new Azure DevOps workspace, complete [workspace provisioning](#set-up-a-new-workspace) first. For an existing workspace, sign in with an account already granted access. Microsoft sign-in alone does not create a workspace or grant a platform role.
* The current connector selects **organizations, not individual projects** and grants access across their visible projects. Project-restricted installation is not supported by this flow. If that is required by your access policy, contact Nullify before connecting; do not approve a whole organization as a substitute.
* All Azure DevOps organizations from one Entra directory must connect to the same Nullify workspace. An organization already connected to another workspace must be disconnected there first; contact Nullify if your workspace design needs a different arrangement.
* Setup requires an Azure DevOps **Project Collection Administrator**. Enabling Microsoft sign-in also requires a consent-granting Entra administrator who is a member of the directory, plus permission to manage identity in Nullify.
* Use a Nullify account with permission to configure connectors. If Microsoft requires administrator approval, an eligible Entra administrator must approve the application; a Project Collection Administrator role in Azure DevOps does not grant that Entra authority. The consenting administrator and the Azure DevOps setup administrator can be different people using the handoff below.
* Confirm the official application with Nullify before accepting consent. The application is named **Nullify** in Nullify’s official directory `44859d25-e6d6-42d9-a98d-e5df5cbc4ac0`, with application ID `37d9fe25-ca83-49ac-a099-054de06b1aad`. A GitHub workspace can use the same Microsoft sign-in application without connecting Azure DevOps or granting ADO setup permissions.

### Set up a new workspace

Nullify prepares the workspace, then sends a setup invitation to the person who will be the first administrator. Sign in at [app.nullify.ai](https://app.nullify.ai/) with your Microsoft work account only to confirm which account you are using. You do not create an app registration, and you do not send Nullify an Entra directory ID or an Azure DevOps organization ID.

{% hint style="warning" %}
**No workspace yet** means this Microsoft account is not linked to a workspace. **Request workspace** on that screen cannot claim a workspace Nullify has already prepared. You did not miss a step. Wait for the setup invitation, then open that link. Do not retry the request form.
{% endhint %}

1. Open the invitation link from Nullify. Keep that browser for the rest of setup. Enter the **Verification code** sent to the approved work email. Each code expires after 10 minutes. The invitation expires after 24 hours. If either expires, ask Nullify for a new invitation rather than starting a different workspace.
2. Choose **Continue with Microsoft** and sign in with your organizational member account. This account becomes the first Nullify workspace administrator. It must also be a Project Collection Administrator in the Azure DevOps organization you will connect. Guest and personal Microsoft accounts cannot complete setup.
3. Complete any Microsoft consent your directory requires. If a different Entra administrator approves the application, return to the original browser and account. That approval does not make your account an Azure DevOps administrator.
4. Choose **Find my Azure DevOps organizations**, then select your organization or enter its name from `dev.azure.com/your-organization`. This is the organization name, not your Entra directory ID. Nullify checks that the organization belongs to the same directory and that your account is an effective Project Collection Administrator. An organization or directory already assigned to another workspace cannot be claimed here.
5. Choose **Activate workspace**. If Microsoft authorization expires, choose **Sign in to Microsoft again** with the same account and retry. Contact Nullify if setup stops partway through. Do not submit a workspace request to get past it.
6. Choose **Sign in and connect Azure DevOps**. Activation lets this account into the workspace and links the directory for later sign-in. It does not install the connector, turn on Microsoft-only sign-in, or start scans. Complete [Connect Azure DevOps](#connect-azure-devops), then choose the repositories to scan during onboarding. Azure Boards credentials alone do not connect source code.

Nullify verifies the approved work mailbox separately from Microsoft sign-in. After activation, add other members and a second administrator from the workspace access controls. Requiring Microsoft sign-in for everyone is a later choice in **Settings → Identity**, described in [Microsoft Entra ID SSO and SCIM](/configuration/account-and-teams/entra-sso-and-scim.md).

### Connect Azure DevOps

1. In the Nullify dashboard, go to **Settings → Connectors**. Open Azure DevOps and choose optional capabilities before clicking **Connect Azure DevOps**:
   * **Also enable Microsoft sign-in** connects the directory for workspace sign-in. The account completing Microsoft sign-in must also be a directory member with an eligible consent-granting Entra administrator role; approval from a separate administrator alone does not satisfy this option. Otherwise, leave it unchecked and configure SSO separately. Existing members still need an identity link or provisioning and an assigned Nullify role; directory membership alone grants no workspace access. See [Microsoft sign-in](/connectors/oidc.md#azure).
   * **Require Nullify review to merge** permits Nullify to manage its required status policy. It is off by default.
   * **File findings as Azure Boards work items** adds work-item read/write and update hooks. It is off by default.
2. For an Azure DevOps-only connection, sign in with the Microsoft work account that has access to the organization. Without an organization name or a verified workspace directory, Microsoft lets you choose the account, and Nullify uses its verified directory to discover organizations. An existing grant can let setup continue without a new administrator-consent prompt. **Also enable Microsoft sign-in** normally starts with administrator consent; a workspace already linked to a verified directory can go straight to sign-in when no organization is named. If Microsoft requires approval, share the consent link with an eligible Entra administrator. Return to the original browser after approval and choose **I've approved it — continue** to authorize again. Approval grants API consent; installation still requires Project Collection Administrator permissions in Azure DevOps. If another person will install, add them to the Nullify workspace with connector-configuration permission and have them start their own connection with their own Microsoft account. If the session has expired, start a new connection.
3. Choose the discovered organizations available to the signed-in account and review its installation eligibility. Discovery is limited to the verified directory used for this sign-in. If the organization is missing, including when you access it as a guest in another directory, return to the connector and enter its **Organization name** to target that organization's directory before signing in again. This is the name from `dev.azure.com/your-organization`, not an Entra directory ID or a project name. The account must still pass the organization's directory and Project Collection Administrator checks; entering a name does not grant access.
4. Review the setup checklist for each organization. A failed step shows a reason and **Retry**; correct that specific issue before retrying. Microsoft sign-in can fail independently while ADO connects, so check both outcomes.
5. Return to **Onboarding**, open **Repositories**, and select the repositories Nullify should review. Choose **Finish setup** to save that selection and request the first scan. Repository selection controls Nullify scanning; it does not reduce the Azure DevOps permissions granted across visible projects. If onboarding is awaiting a staff start, contact your Nullify representative; a connected organization does not confirm a running scan.

### What Nullify does automatically

After Microsoft authorization and organization confirmation, Nullify (via its own Microsoft app — no customer-side app registration involved):

1. Adds Nullify's service principal to your organisation as a user with **Basic** access.
2. Grants that service principal the **Service Hooks (View & Edit)** permission at the organisation level.
3. Grants it the least-privilege Azure DevOps permissions listed under [Permissions](#permissions) on **every project in each organisation you connected** — you choose organisations, not projects. Service Hook permissions are organization-wide; repository permissions are project-scoped. This includes write permissions for reviews and autofix and is not a read-only installation.
4. Checks that those permissions actually took effect, by listing repositories, reading a default branch, and asking Azure DevOps whether a pull request comment would be permitted. Anything that did not take shows on the checklist with the exact setting to change.
5. Creates the service hook subscriptions that stream Git events to Nullify — plus the work-item event, but only if you ticked **File findings as Azure Boards work items** (see [Azure DevOps connector](/connectors/azure.md#events-the-connector-subscribes-to) for the event list).
6. Saves your repository catalog independently of the first scan. New shared-app installations wait for repository selection: choose repositories in Onboarding and **Finish setup** before the first scan is requested. Existing enrollment selections are preserved.

Nullify never asks for a password or a personal access token. The delegated Microsoft access token used for setup is stored encrypted while the connection session remains active so that **Retry** can finish failed steps. Successful setup clears it; a failed session retains it until session expiry. Confirmation and retries extend the session, but do not refresh an expired Microsoft access token; start a new connection if Microsoft authorization has expired. Ongoing API calls (reading pull requests, posting reviews, syncing tickets) run as the service principal itself. Nullify manages the application credential; you do not copy it into your workspace.

### Permissions

During setup, Microsoft authorization requests `499b84ac-1321-427f-aa17-267ca6975798/user_impersonation` (delegated Azure DevOps access) and `openid profile email`. Microsoft sign-in proves the setup administrator's identity and issues the delegated token so Nullify can add its service principal and configure permissions. This ADO scope is required even when **Also enable Microsoft sign-in** is unchecked; that option controls workspace sign-in configuration, not the setup scopes. The separate SSO-only flow requests only `openid profile email`.

Ongoing calls use the application's own identity. Microsoft Entra application permissions do not grant that identity access to Azure DevOps: organization membership, Basic access and Azure DevOps resource permissions do. See [Microsoft's application identity guidance](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity?view=azure-devops).

Every resource permission below is an Azure DevOps access control entry, configured with the signed-in Azure DevOps setup administrator's authority and auditable in Azure DevOps.

#### What Nullify grants itself

| Azure DevOps security namespace | Scope (token)                                                                         | Permissions granted                      | Why                                                                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Service Hooks (`cb594ebe-…`)    | Organisation (`PublisherSecurity`)                                                    | `ViewSubscriptions`, `EditSubscriptions` | Create and repair the webhook subscriptions that deliver push, pull request and work-item events                                                                                                                                                                                                                                                                                                  |
| Git Repositories (`2e9eb7ed-…`) | Each connected project (`repoV2/{projectId}`)                                         | `GenericRead`                            | Clone and read files, branches and pull request diffs — every scan and review                                                                                                                                                                                                                                                                                                                     |
| Git Repositories                | Each connected project                                                                | `GenericContribute`                      | Push an autofix branch, and set the commit status the "Nullify" check reports through                                                                                                                                                                                                                                                                                                             |
| Git Repositories                | Each connected project                                                                | `PullRequestContribute`                  | Post and reply to review comments, and react to them                                                                                                                                                                                                                                                                                                                                              |
| Git Repositories                | Each repository’s `refs/heads/nullify/` branch folder                                 | `CreateBranch`                           | Create the autofix branch                                                                                                                                                                                                                                                                                                                                                                         |
| Git Repositories                | Each repository’s `refs/heads/nullify/` branch folder                                 | `ForcePush`                              | Re-point an existing autofix branch after a rebase, which is a non-fast-forward update Azure DevOps refuses without it                                                                                                                                                                                                                                                                            |
| Git Repositories                | Each connected project                                                                | `EditPolicies`                           | **Only when you tick "Require Nullify review to merge".** Lets Nullify create, edit and remove branch policies on that project — there is no narrower permission for managing the required "Nullify" status check, which is why the gate is opt-in and off by default. Nullify still holds neither `PolicyExempt` nor `PullRequestBypassPolicy`, so it can manage its own gate and bypass nothing |
| Project (`52d39943-…`)          | Each connected project (`$PROJECT:vstfs:///Classification/TeamProject/{projectId}`)   | `GENERIC_READ`                           | Resolve the project every repository and work-item call is made against                                                                                                                                                                                                                                                                                                                           |
| Build (`33344d9c-…`)            | Each connected project (`{projectId}`)                                                | `ViewBuilds`                             | Read a build's timeline and logs, so a review can explain which pipeline step failed                                                                                                                                                                                                                                                                                                              |
| Library (`b7e84409-…`)          | Each connected project (`Library/{projectId}`)                                        | `View`                                   | Read the one pipeline variable group Nullify looks for (`nullify`), which carries the environment a DAST run needs                                                                                                                                                                                                                                                                                |
| Area paths / CSS (`83e28ad4-…`) | Each connected project's root area path (`vstfs:///Classification/Node/{areaNodeId}`) | `WORK_ITEM_READ`, `WORK_ITEM_WRITE`      | **Only when you tick "File findings as Azure Boards work items".** Files a finding as a work item and syncs its state back. A workspace that files findings elsewhere is never granted work-item access, and never gets the work-item service hook either                                                                                                                                         |

Bit values are never hard-coded: Nullify reads each namespace's own action table from your organisation and resolves the permissions above by name, so a grant cannot silently widen if Microsoft renumbers a namespace.

#### What Nullify never grants itself

| Not granted                                                                 | Why it matters                                                                                                                                                                                                                                                                                     |
| --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Administer`, `ManagePermissions` (Git Repositories)                        | Nullify cannot change anyone's permissions, including its own                                                                                                                                                                                                                                      |
| `CreateRepository`, `DeleteRepository`, `RenameRepository`                  | Nullify cannot create, delete or rename a repository                                                                                                                                                                                                                                               |
| `PolicyExempt`, `PullRequestBypassPolicy`                                   | Nullify cannot bypass a branch policy — including its own required check                                                                                                                                                                                                                           |
| `EditPolicies` (Git Repositories)                                           | Not granted unless you tick **Require Nullify review to merge**; see the granted table above. A workspace that leaves the gate off never gives Nullify branch-policy access at all                                                                                                                 |
| `GENERIC_WRITE`, `DELETE` (Project)                                         | Nullify cannot administer or delete a project                                                                                                                                                                                                                                                      |
| `QueueBuilds`, `EditBuildQuality` (Build) and `Administer`, `Use` (Library) | Nullify reads build logs and one variable group; it cannot queue a build or consume a variable group in a pipeline of its own                                                                                                                                                                      |
| **Project Collection Administrator**                                        | Never requested for Nullify's service principal. The connect flow asks *you* to hold it for the one-time setup, then leaves Nullify at least privilege                                                                                                                                             |
| Member Entitlement Management (organisation roster)                         | Reading your organisation's user roster is only grantable by making Nullify an organisation administrator. Nullify does not take it: reviewer suggestion and contributor attribution fall back to each project's team membership instead, and the checklist records that the capability is reduced |
| Organisation graph / "View instance-level information"                      | Same reasoning: Nullify skips checks that a user belongs to the organisation rather than taking organisation-wide read                                                                                                                                                                             |

Azure DevOps **Code Search** is an extension (`ms.vss-code-search`), not a permission — no grant turns it on. If it is not installed for your organisation, Nullify's repository-wide code search is skipped and the checklist says so; install it from the Azure DevOps marketplace to enable it.

#### If your organisation refuses the permission write

Some organisations restrict who may write access control entries, even for a Project Collection Administrator. The affected checklist step then fails and names the setting to change. You have two options:

1. **Preferred — grant the same permissions by hand.** Each failed step names the exact Azure DevOps page (for example **Project settings → Repositories → Security** for the Git Repositories permissions above), then press **Retry**.
2. **Coarser — add Nullify's service principal to a project group.** The project's built-in **Contributors** group under **Project settings → Permissions** may cover some required permissions, but is not a substitute for the full table above. In particular, check the scoped autofix branch and optional policy permissions separately. Group membership can grant broader access; Nullify never adds it on your behalf. Review effective permissions and retry the checklist with your security administrator.

#### Revoking

Use **Disconnect** in Nullify's Azure DevOps connector to remove its hooks and routing. Also remove the service principal from **Organization settings → Users** when revoking its organization access. Removing the principal alone does not delete existing hook subscriptions. The Entra enterprise application and Microsoft sign-in configuration are separate; deleting the shared enterprise application can disrupt both ADO and Microsoft sign-in.

### Troubleshooting

The live checklist links directly to these fixes; this section is the same content for reference.

#### Basic access or billing blocks setup

Nullify requires Basic access in each connected organization. Application identities consume their assigned paid access level separately in each organization; user subscription benefits do not apply. Check capacity and billing under **Organization settings → Billing**, then **Retry**. See [Microsoft’s application identity licensing guidance](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity?view=azure-devops#licensing).

#### "Organization isn't Entra-backed"

Some Azure DevOps organisations (personal Microsoft accounts, or organisations never linked to an Entra tenant) have no Entra tenant for Nullify's consent screen to target, and the PAT-based connection they would need is [not yet supported](#not-yet-supported). Link the organisation to your Entra tenant under **Organization settings → Microsoft Entra**, then connect again, or contact your Nullify representative.

#### Conditional Access or IP policy is blocking Nullify

If your tenant's Conditional Access policies or Azure DevOps organisation IP allow-list reject Nullify's service principal, allow-list Nullify's egress IP ranges.

{% hint style="info" %}
Ask your Nullify representative for the current egress ranges to allow-list. Setup and token requests run from the shared router; repository, scan and ticket operations also run from your customer stack. Confirm the ranges for both deployments rather than allowing only the router's addresses.
{% endhint %}

#### User consent is blocked and nothing happens after clicking Connect

Use the administrator consent link shown in Nullify and return to the original browser after approval, as described in step 2. If your session expires, start again. If Microsoft rejects the app entirely, ask your Entra administrator to inspect Nullify's official application under **Enterprise applications**.

#### Microsoft shows "unverified publisher"

Check the application ID against the official production ID above, then follow your organization's approval or exception process. Publisher verification and Azure DevOps Marketplace listing are separate from installation; neither substitutes for your administrator's consent. Nullify cannot bypass a Microsoft policy that blocks the application. Ask Nullify for the current verification status if your review requires it.

#### Removing Nullify's access

Disconnect in Nullify, remove unwanted ADO organization membership, and verify that hooks and scan delivery have stopped. ADO disconnect does not disconnect the workspace's Microsoft sign-in directory. For SSO revocation and safe recovery, follow [Microsoft sign-in](/connectors/oidc.md#azure); Entra-only workspaces must retain a usable administrator before changing identity access.

### Capability differences vs GitHub

* **No blame API.** Azure DevOps has no per-line blame endpoint, so Nullify falls back to the file's most recent contributor (from commit history) wherever it would otherwise use blame — for example, suggesting a reviewer or owner.
* **No force-push detection.** Nullify does not attempt to detect or react to force-pushes on *your* Azure DevOps branches the way it does on GitHub; each push is handled independently. Nullify does force-push its own autofix branch when it repoints one, which is what the `ForcePush` grant above is for.
* **PR review comments are iteration-tracked, not diff-anchored the same way.** Azure DevOps threads a comment to a pull request *iteration* (its update sequence) rather than a specific commit SHA the way GitHub does, so Nullify's review comments are anchored to the iteration they were posted against.

### Tenants

Nullify prepares a workspace before a Microsoft sign-in can open it. An unlinked Microsoft account sees **No workspace yet** and cannot create the workspace from that screen. Use the [setup invitation](#set-up-a-new-workspace). Connecting the directory, or holding an Entra administrator role, does not grant every directory member a Nullify role.

### Not yet supported

These connection types are not available yet. The dashboard does not offer them, and the API refuses them, because every scan, webhook and ticket call Nullify makes authorizes through Nullify's own Microsoft app, which neither connection type can use.

* **Azure DevOps Server (on-premises).** Connecting a Server collection with a Personal Access Token is planned for Azure DevOps Server 2022.1 and later.
* **Bring your own service principal.** Connecting Azure DevOps Services through a service principal your team registers, instead of Nullify's shared Microsoft app, is planned.

Contact your Nullify representative if you need either of these.

### Webhook credentials

Azure DevOps service hooks use an installation-specific secret. During a migration from legacy shared credentials, coordinate hook updates with Nullify before strict signature enforcement is enabled; deliveries using the old shared credential can be rejected. Keep each organization's hook credential paired with its own installation.
