Skip to main content

Check out Port for yourself ➜ 

Ingest GitLab security vulnerabilities into Port

Custom Ocean integration

This integration was created using the custom Ocean integration builder.
Please note that:

  1. This integration will not be listed in the Data sources page of your Port application, and must be installed manually using the instructions on this page.
  2. This integration will not create components (e.g. blueprints, mapping, etc.) in your portal automatically, you will need to create them manually using the instructions on this page.

Port's GitLab integration ingests projects, merge requests, pipelines, and other core resources, but does not cover security vulnerability findings. This guide adds that missing piece using a lightweight Ocean Custom Integration that calls GitLab's Vulnerability Findings API and relates each finding back to the gitlabRepository entities your existing integration already creates.

The result is centralized visibility into SAST, DAST, dependency scanning, and container scanning findings per project and team alongside your existing engineering data.

Common use cases

  • See security findings per project and team to identify ownership gaps and risk areas.
  • Build scorecards tracking which projects have security scanning enabled and meet vulnerability thresholds.
  • Provide leadership with dashboards showing security posture alongside Engineering Intelligence metrics.

Prerequisites

This guide assumes the following:

Install the custom integration

Since the existing GitLab integration does not support vulnerability findings as a resource kind, we use a separate Ocean Custom Integration that targets the same GitLab API but fetches only security data. It uses the same GitLab Personal Access Token.

  1. Go to your Data sources page.

  2. Click + Data source and select Custom Integration.

  3. Fill in the connection settings:

    SettingValue
    Base URLhttps://gitlab.com (or your self-managed URL)
    Auth Typebearer_token
    API TokenYour GitLab Personal Access Token
    Pagination Typepage
    Identifiermy-ocean-gitlab-vul
  4. Click Save & Continue.

Set up data model

Create a gitlab_vulnerability blueprint that relates each finding to a gitlabRepository entity from your existing GitLab integration.

  1. Go to the Builder page of your portal.

  2. Click on + Blueprint, then the {...} Edit JSON button in the top right corner of the modal.

  3. Add the JSON schema below and click Save:

    GitLab vulnerability blueprint (click to expand)
    {
    "identifier": "gitlab_vulnerability",
    "description": "A security vulnerability finding detected by GitLab's security scanners (SAST, DAST, dependency scanning, container scanning).",
    "title": "GitLab Vulnerability",
    "icon": "GitLab",
    "schema": {
    "properties": {
    "report_type": {
    "type": "string",
    "title": "Report type",
    "description": "The type of security scan that detected this vulnerability",
    "enum": ["sast", "dast", "dependency_scanning", "container_scanning"],
    "enumColors": {
    "sast": "blue",
    "dast": "turquoise",
    "dependency_scanning": "orange",
    "container_scanning": "purple"
    }
    },
    "severity": {
    "type": "string",
    "title": "Severity",
    "enum": ["critical", "high", "medium", "low", "info", "unknown"],
    "enumColors": {
    "critical": "red",
    "high": "orange",
    "medium": "yellow",
    "low": "green",
    "info": "blue",
    "unknown": "lightGray"
    }
    },
    "state": {
    "type": "string",
    "title": "State",
    "description": "The current state of the vulnerability finding",
    "enum": ["detected", "confirmed", "dismissed", "resolved"],
    "enumColors": {
    "detected": "yellow",
    "confirmed": "red",
    "dismissed": "lightGray",
    "resolved": "green"
    }
    },
    "scanner_name": {
    "type": "string",
    "title": "Scanner"
    },
    "description": {
    "type": "string",
    "title": "Description"
    },
    "solution": {
    "type": "string",
    "title": "Solution"
    },
    "file_path": {
    "type": "string",
    "title": "File path"
    },
    "start_line": {
    "type": "number",
    "title": "Start line"
    },
    "false_positive": {
    "type": "boolean",
    "title": "False positive"
    },
    "identifiers": {
    "type": "array",
    "title": "Identifiers",
    "description": "CVE, CWE, and other vulnerability identifiers"
    },
    "project_name": {
    "type": "string",
    "title": "Project name"
    },
    "url": {
    "type": "string",
    "format": "url",
    "title": "URL"
    }
    },
    "required": ["report_type", "severity"]
    },
    "mirrorProperties": {},
    "calculationProperties": {},
    "aggregationProperties": {},
    "relations": {
    "project": {
    "title": "Project",
    "target": "gitlabRepository",
    "required": false,
    "many": false
    }
    }
    }

Configure the mapping

The mapping uses nested endpoints to iterate over all GitLab projects and fetch vulnerability findings for each one.

  1. Go to your data sources page and open the GitLab vulnerabilities integration.

  2. Add the resource mapping below.

    Vulnerability findings mapping (click to expand)
    resources:
    - kind: /api/v4/projects/{project_id}/vulnerability_findings
    selector:
    query: .uuid != null
    query_params:
    scope: all
    per_page: '100'
    path_parameters:
    project_id:
    endpoint: /api/v4/groups/<group_name>/projects
    method: GET
    query_params:
    include_subgroups: 'true'
    data_path: .
    field: .id
    filter: .id > 0
    port:
    entity:
    mappings:
    identifier: .uuid
    title: .name
    blueprint: '"gitlab_vulnerability"'
    properties:
    report_type: .report_type
    severity: .severity
    state: .state
    scanner_name: .scanner.name
    description: .description
    solution: .solution
    file_path: .location.file
    start_line: .location.start_line // 0
    false_positive: .false_positive
    identifiers: >-
    [.identifiers[] | {type: .external_type, id: .external_id, name:
    .name, url: .url}]
    project_name: .project.name
    url: '"https://gitlab.com" + (.blob_path // "")'
    relations:
    project: .project.full_path | ltrimstr("/")
    Mapping and scope

    Replace group_name in the endpoint with your GitLab group's URL-encoded path. The include_subgroups=true parameter includes projects from nested subgroups. The filter uses .id > 0 instead of true because the Port backend can parse the YAML literal 'true' as a boolean True, which is not valid JQ. Using GET /api/v4/projects or GET /api/v4/projects?membership=true is not recommended because they return projects across all groups and tiers, and non-Ultimate projects will return 403 on the vulnerability findings endpoint.

Add aggregation properties to gitlabRepository

Scorecard rules that count related vulnerabilities use aggregation properties on the gitlabRepository blueprint. Add these so the scorecard conditions have valid properties to reference.

  1. Go to the Builder page and select gitlabRepository.

  2. Click {...} and choose Edit JSON.

  3. Locate the aggregationProperties object (add it if missing). Merge in the following three properties so each repository can expose counts of related vulnerabilities by scan type and severity:

    Aggregation properties JSON (click to expand)
    {
    "sast_findings_count": {
    "title": "SAST findings count",
    "target": "gitlab_vulnerability",
    "pathFilter": [{ "path": ["project"], "fromBlueprint": "gitlab_vulnerability" }],
    "calculationSpec": { "calculationBy": "entities", "func": "count" },
    "query": {
    "combinator": "and",
    "rules": [{ "property": "report_type", "operator": "=", "value": "sast" }]
    }
    },
    "dependency_scanning_findings_count": {
    "title": "Dependency scanning findings count",
    "target": "gitlab_vulnerability",
    "pathFilter": [{ "path": ["project"], "fromBlueprint": "gitlab_vulnerability" }],
    "calculationSpec": { "calculationBy": "entities", "func": "count" },
    "query": {
    "combinator": "and",
    "rules": [{ "property": "report_type", "operator": "=", "value": "dependency_scanning" }]
    }
    },
    "critical_unresolved_vulns_count": {
    "title": "Critical unresolved vulnerabilities count",
    "target": "gitlab_vulnerability",
    "pathFilter": [{ "path": ["project"], "fromBlueprint": "gitlab_vulnerability" }],
    "calculationSpec": { "calculationBy": "entities", "func": "count" },
    "query": {
    "combinator": "and",
    "rules": [
    { "property": "severity", "operator": "=", "value": "critical" },
    { "property": "state", "operator": "!=", "value": "resolved" },
    { "property": "state", "operator": "!=", "value": "dismissed" }
    ]
    }
    }
    }
  4. Save the blueprint.

Set up scorecards

Add a scorecard to the gitlabRepository blueprint to track scanning adoption and vulnerability health.

  1. Go to the Builder page and select gitlabRepository.

  2. Click the Scorecards tab, then + New scorecard.

  3. Paste the JSON below (it uses the aggregation properties from the previous section). Click Save.

    Security scanning coverage scorecard (click to expand)
    {
    "identifier": "security_scanning_coverage",
    "title": "Security Scanning Coverage",
    "levels": [
    { "title": "Basic", "color": "paleBlue" },
    { "title": "Bronze", "color": "bronze" },
    { "title": "Silver", "color": "silver" },
    { "title": "Gold", "color": "gold" }
    ],
    "rules": [
    {
    "identifier": "has_sast_findings",
    "title": "SAST scanning enabled",
    "description": "Project has SAST scanning configured and producing findings",
    "level": "Gold",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": ">",
    "property": "sast_findings_count",
    "value": 0
    }
    ]
    }
    },
    {
    "identifier": "has_dependency_scanning",
    "title": "Dependency scanning enabled",
    "description": "Project has dependency scanning configured and producing findings",
    "level": "Silver",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": ">",
    "property": "dependency_scanning_findings_count",
    "value": 0
    }
    ]
    }
    },
    {
    "identifier": "no_critical_vulns",
    "title": "No critical vulnerabilities",
    "description": "Project has zero unresolved critical-severity findings",
    "level": "Gold",
    "query": {
    "combinator": "and",
    "conditions": [
    {
    "operator": "=",
    "property": "critical_unresolved_vulns_count",
    "value": 0
    }
    ]
    }
    }
    ]
    }

Visualize security posture

After data is ingested, we can create a dashboard to visualize the security posture of our GitLab repositories.

Create a dashboard

  1. Go to the Catalog page and click + > New dashboard.

  2. Name it GitLab Security Posture, add a description, and click Create.

Add widgets

Total vulnerabilities widget (click to expand)
  1. Click + Widget and select Number Chart.

  2. Fill in the following details:

    • Title: Total Vulnerabilities.
    • Icon: Alert.
    • Blueprint: gitlab_vulnerability.
    • Chart type: Count entities.
    • Function: count.
  3. Click Save.

Critical vulnerabilities widget (click to expand)
  1. Click + Widget and select Number Chart.

  2. Fill in the following details:

    • Title: Critical Vulnerabilities.
    • Icon: Alert.
    • Blueprint: gitlab_vulnerability.
    • Chart type: Count entities.
    • Function: count.
    • Add a filter: severity = critical and state != resolved and state != dismissed.
  3. Click Save.

High severity vulnerabilities widget (click to expand)
  1. Click + Widget and select Number Chart.

  2. Fill in the following details:

    • Title: High Severity.
    • Icon: Alert.
    • Blueprint: gitlab_vulnerability.
    • Chart type: Count entities.
    • Function: count.
    • Add a filter: severity = high and state != resolved and state != dismissed.
  3. Click Save.

Vulnerabilities by severity pie chart (click to expand)
  1. Click + Widget and select Pie chart.

  2. Fill in the following details:

    • Title: Vulnerabilities by Severity.
    • Icon: Alert.
    • Blueprint: gitlab_vulnerability.
    • Breakdown by property: severity.
  3. Click Save.

Vulnerabilities by scan type pie chart (click to expand)
  1. Click + Widget and select Pie chart.

  2. Fill in the following details:

    • Title: Vulnerabilities by Scan Type.
    • Icon: GitLab.
    • Blueprint: gitlab_vulnerability.
    • Breakdown by property: report_type.
  3. Click Save.

Vulnerabilities by state bar chart (click to expand)
  1. Click + Widget and select Bar Chart.

  2. Fill in the following details:

    • Title: Vulnerabilities by State.
    • Icon: DefaultProperty.
    • Blueprint: gitlab_vulnerability.
    • Breakdown by property: state.
  3. Click Save.

Vulnerabilities by project bar chart (click to expand)
  1. Click + Widget and select Bar Chart.

  2. Fill in the following details:

    • Title: Vulnerabilities by Project.
    • Icon: GitLab.
    • Blueprint: gitlab_vulnerability.
    • Breakdown by property: project_name.
  3. Click Save.

Vulnerability findings table (click to expand)
  1. Click + Widget and select Table.

  2. Fill in the following details:

    • Title: All Vulnerability Findings.
    • Blueprint: gitlab_vulnerability.
  3. Click Save.

  4. Click ... on the widget and select Customize table.

  5. Under Manage Properties, add:

    • report_type.
    • severity.
    • state.
    • scanner_name.
    • project_name.
    • file_path.
    • false_positive.
    • solution.
  6. Click the save icon in the top right corner of the widget.

Next steps

  • Automate on critical findings: Set up automations that create a Jira ticket or send a Slack notification when critical vulnerabilities are detected.
  • Build team-level views: Use Port's team ownership to group vulnerabilities by team and surface security debt per squad.