FormatURL

Strips, unquotes and unescapes URLs. If the URL is a Proofpoint or ATP URL, extracts its redirect URL. If more than one URL is passed to the formatter, the separator must be a pipe ("|").

python · Common Scripts

Details

IDFormatURL
Languagepython
From Version5.5.0
Docker Imagedemisto/python3:3.12.13.10404775
Tagsindicator-format

README

Strips, unquotes and unescapes URLs. If the URL is a Proofpoint or ATP URL, extracts its redirect URL.
If more than one URL is passed to the formatter, the separator must be a pipe (“|”).

Script Data


Name Description
Script Type python3
Tags indicator-format
Cortex XSOAR Version 5.5.0

Inputs


Argument Name Description  
input A pipe (“ ”) separated list of URL inputs.

Outputs


Path Description Type
URL URL formatted. String

Script Example

!FormatURL input=https://urldefense.proofpoint.com/v2/url?u=https-3A__example.com_something.html

Context Example

{
    "URL": [
        "https://example.com/something.html"
    ]
}

Human Readable Output

https://example.com/something.html

import demistomock as demisto
import FormatURL


def test_formatter(mocker):
    mocker.patch.object(demisto, "args", return_value={"input": "https://www.test.com"})
    mocker.patch.object(demisto, "results")

    FormatURL.main()

    results = demisto.results.call_args[0]

    assert results[0]["Contents"] == ["https://www.test.com"]


def test_failed_formatter(mocker):
    mocker.patch.object(demisto, "args", return_value={"input": "https://@www.test.com"})
    mocker.patch.object(demisto, "results")

    FormatURL.main()

    results = demisto.results.call_args[0]

    assert results[0]["Contents"] == [""]


def test_bad(mocker):
    mocker.patch.object(demisto, "args", return_value={"input": 1})
    return_error = mocker.patch.object(FormatURL, "return_error")
    FormatURL.main()
    return_error.assert_called_once()


def test_proofpoint_v3(mocker):
    """Given
        - A Proofpoint v3 URL as input.

    When
        - The FormatURL.main() function is executed.

    Then
        - The extracted URL should be correctly formatted.
    """
    mocker.patch.object(
        demisto,
        "args",
        return_value={
            "input": "https://urldefense.com/v3/__https://google.com:443/search?q=a*test&gs=ps__;Kw!-612Flbf0JvQ3kNJkRi5Jg!Ue6tQudNKaShHg93trcdjqDP8se2ySE65jyCIe2K1D_uNjZ1Lnf6YLQERujngZv9UWf66ujQIQ$"
        },
    )
    mock_result = mocker.patch.object(demisto, "results")
    FormatURL.main()
    assert mock_result.call_args[0][0]["Contents"][0] == "https://google.com:443/search?q=a+test&gs=ps"


def test_proofpoint_v1(mocker):
    """Given
        - A Proofpoint v1 URL as input.

    When
        - The FormatURL.main() function is executed.

    Then
        - The extracted URL should be correctly formatted.
    """
    mocker.patch.object(
        demisto,
        "args",
        return_value={
            "input": "https://urldefense.proofpoint.com/v1/url?u=http://www.bouncycastle.org/&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=IKM5u8%2B%2F%2Fi8EBhWOS%2BqGbTqCC%2BrMqWI%2FVfEAEsQO%2F0Y%3D%0A&m=Ww6iaHO73mDQpPQwOwfLfN8WMapqHyvtu8jM8SjqmVQ%3D%0A&s=d3583cfa53dade97025bc6274c6c8951dc29fe0f38830cf8e5a447723b9f1c9a"
        },
    )
    mock_result = mocker.patch.object(demisto, "results")
    FormatURL.main()
    assert mock_result.call_args[0][0]["Contents"][0] == "http://www.bouncycastle.org/"


def test_proofpoint_v2(mocker):
    """Given
        - A Proofpoint v2 URL as input.

    When
        - The FormatURL.main() function is executed.

    Then
        - The extracted URL should be correctly formatted.
    """
    mocker.patch.object(
        demisto,
        "args",
        return_value={
            "input": "https://urldefense.proofpoint.com/v2/url?u=https-3A__media.mnn.com_assets_images_2016_06_jupiter-2Dnasa.jpg.638x0-5Fq80-5Fcrop-2Dsmart.jpg&d=DwMBaQ&c=Vxt5e0Osvvt2gflwSlsJ5DmPGcPvTRKLJyp031rXjhg&r=BTD8MPjq1qSLi0tGKaB5H6aCJZZBjwYkLyorZdRQrnY&m=iKjixvaJuqvmReS78AB0JiActTrR_liSq7lDRjEQ9DE&s=-M8Vz-GV-kqkNVf1BAtv38DdudAHVDAI6_jQQLVmleE&e="
        },
    )
    mock_result = mocker.patch.object(demisto, "results")
    FormatURL.main()
    assert (
        mock_result.call_args[0][0]["Contents"][0]
        == "https://media.mnn.com/assets/images/2016/06/jupiter-nasa.jpg.638x0_q80_crop-smart.jpg"
    )


def test_missing_slash_before_query(mocker):
    """Given
        - A URL with query parameters but no path (missing / before ?).

    When
        - The FormatURL.main() function is executed.

    Then
        - A forward slash should be added after the domain before the query string.
    """
    mocker.patch.object(
        demisto,
        "args",
        return_value={"input": "https://example.com?test=value"},
    )
    mock_result = mocker.patch.object(demisto, "results")
    FormatURL.main()
    result = mock_result.call_args[0][0]["Contents"][0]
    assert result == "https://example.com/?test=value", f"Expected 'https://example.com/?test=value', got: {result}"


def test_missing_slash_before_fragment(mocker):
    """Given
        - A URL with fragment but no path (missing / before #).

    When
        - The FormatURL.main() function is executed.

    Then
        - A forward slash should be added after the domain before the fragment.
    """
    mocker.patch.object(
        demisto,
        "args",
        return_value={"input": "https://example.com#section"},
    )
    mock_result = mocker.patch.object(demisto, "results")
    FormatURL.main()
    result = mock_result.call_args[0][0]["Contents"][0]
    assert result == "https://example.com/#section", f"Expected 'https://example.com/#section', got: {result}"


def test_missing_slash_with_port_and_query(mocker):
    """Given
        - A URL with port and query parameters but no path (missing / before ?).

    When
        - The FormatURL.main() function is executed.

    Then
        - A forward slash should be added after the port before the query string.
    """
    mocker.patch.object(
        demisto,
        "args",
        return_value={"input": "http://example.com:8080?query=1"},
    )
    mock_result = mocker.patch.object(demisto, "results")
    FormatURL.main()
    result = mock_result.call_args[0][0]["Contents"][0]
    assert result == "http://example.com:8080/?query=1", f"Expected 'http://example.com:8080/?query=1', got: {result}"


def test_missing_slash_with_port_and_fragment(mocker):
    """Given
        - A URL with port and fragment but no path (missing / before #).

    When
        - The FormatURL.main() function is executed.

    Then
        - A forward slash should be added after the port before the fragment.
    """
    mocker.patch.object(
        demisto,
        "args",
        return_value={"input": "http://example.com:8080#fragment"},
    )
    mock_result = mocker.patch.object(demisto, "results")
    FormatURL.main()
    result = mock_result.call_args[0][0]["Contents"][0]
    assert result == "http://example.com:8080/#fragment", f"Expected 'http://example.com:8080/#fragment', got: {result}"