{"id":27976466,"url":"https://github.com/misp/misp-guard","last_synced_at":"2025-07-28T09:37:50.888Z","repository":{"id":65041625,"uuid":"534666833","full_name":"MISP/misp-guard","owner":"MISP","description":"misp-guard is a mitmproxy addon that inspects and blocks outgoing events to external MISP instances via sync mechanisms (pull/push) based on a set of customizable block rules.","archived":false,"fork":false,"pushed_at":"2025-02-11T08:49:48.000Z","size":157,"stargazers_count":14,"open_issues_count":0,"forks_count":3,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-08T01:34:14.780Z","etag":null,"topics":["air-gapped","misp","misp-api","misp-guard"],"latest_commit_sha":null,"homepage":"https://www.misp-project.org/2022/09/13/misp-guard.html/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MISP.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-09-09T14:02:33.000Z","updated_at":"2025-02-12T18:15:27.000Z","dependencies_parsed_at":"2023-11-21T10:35:17.108Z","dependency_job_id":"c3caaec9-1790-4720-b338-71d94aae371f","html_url":"https://github.com/MISP/misp-guard","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/MISP/misp-guard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MISP%2Fmisp-guard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MISP%2Fmisp-guard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MISP%2Fmisp-guard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MISP%2Fmisp-guard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MISP","download_url":"https://codeload.github.com/MISP/misp-guard/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MISP%2Fmisp-guard/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261987701,"owners_count":23240895,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["air-gapped","misp","misp-api","misp-guard"],"created_at":"2025-05-08T01:27:06.438Z","updated_at":"2025-07-28T09:37:50.869Z","avatar_url":"https://github.com/MISP.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# misp-guard\n`misp-guard` is a [mitmproxy](https://mitmproxy.org/) addon designed to apply configurable filters that prevent the unintentional leakage of sensitive threat intelligence data while facilitating controlled information sharing.\n\n`misp-guard` functions as a proxy specifically designed to interact with and understand the MISP synchronization protocol. It monitors communications between MISP instances, allowing for real-time inspection and enforcement of security policies. MISP Guard effectively blocks incoming or outgoing data that matches configured filtering rules, ensuring sensitive or restricted information is not unintentionally shared.\n\n\u003e **NOTE: By default this addon will block all outgoing HTTP requests that are not required during a MISP server sync. However, individual URLs or domains can be allowed if necessary.**\n\n## Objectives\nTo prevent data leakage in high-security environments such as military networks or critical infrastructure systems, `misp-guard` plays a crucial role by acting as a configurable enforcement layer during MISP instance synchronization. Its fine-grained filtering capabilities allow organizations to maintain strict control over what information is shared, ensuring compliance with compartmentalization policies and mitigating the risk of accidental data exposure.\n\n**Supported block rules:**\n* `compartments_rules`: Compartments can be interpreted as a VLAN where one or more MISP are living, each compartment defines to which other compartments allows to sync.\n* `taxonomies_rules`:\n  * `required_taxonomies`: Taxonomies that have to be present in a event, otherwise it will be blocked.\n  * `allowed_tags`: For each of the `required_taxonomies` a subset of allowed tags can be specified.\n  * `blocked_tags`: Tags that cannot be present in any of the event entities.\n* `blocked_distribution_levels`: Blocks if the event/objects/attributes matches one of the blocked distribution levels.\n  * `\"0\"`: Organisation Only\n  * `\"1\"`: Community Only\n  * `\"2\"`: Connected Communities\n  * `\"3\"`: All Communities\n  * `\"4\"`: Sharing Group\n  * `\"5\"`: Inherit Event\n* `blocked_sharing_groups_uuids`: Blocks if the event/objects/attributes matches one of the blocked sharing groups uuids.\n* `blocked_attribute_types`: Blocks if the event contains an attribute matching one of this types.\n* `blocked_attribute_categories`: Blocks if the event contains an attribute matching one of this categories.\n* `blocked_object_types`: Blocks if the event contains an object matching one of this types.\n\n**Allowlist**\n\n* To allow individual URLs or domains, simply add them as a JSON array under the `allowlist` element.\n  * `urls` The entire URL is checked and only exact calls are allowed.\n  * `domains` In contrast, only the domain is checked and any website behind the domain can be queried. Should only be used if adding exact URLs is not possible.\n\nSee sample config [here](src/test/test_config.json).\n\n## PUSH\n```mermaid\nsequenceDiagram\n    participant MISP A \n    participant MISP Guard\n    participant MISP B\n\n    rect rgb(191, 223, 255)\n    note right of MISP A: PUSH Events \n\n    MISP B-\u003e\u003eMISP Guard: [GET]/servers/getVersion\n    MISP Guard-\u003e\u003eMISP A: [GET]/servers/getVersion\n    MISP A-\u003e\u003eMISP Guard: [GET]/servers/getVersion\n    MISP Guard-\u003e\u003eMISP B: [GET]/servers/getVersion\n    \n    MISP B-\u003e\u003eMISP Guard: [HEAD]/events/view/[UUID]\n    note right of MISP Guard: Only `minimal` search requests to /events/index are allowed\n    MISP Guard-\u003e\u003eMISP A: [HEAD]/events/view/[UUID]\n    MISP A-\u003e\u003eMISP Guard: [HEAD]/events/view/[UUID]\n    MISP Guard-\u003e\u003eMISP B: [HEAD]/events/view/[UUID]\n    \n    rect rgb(191, 223, 255)\n    note left of MISP Guard: 404: If the event does not exists in MISP A\n    MISP B-\u003e\u003e+MISP Guard: [POST]/events/add\n    note right of MISP Guard: Outgoing Event is inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [POST]/events/add\n    MISP A-\u003e\u003eMISP Guard: [POST]/events/add\n    MISP Guard-\u003e\u003eMISP B: [POST]/events/add\n    end\n\n    rect rgb(191, 223, 255)\n    note left of MISP Guard: 200: If the event already exists in MISP A\n    MISP B-\u003e\u003e+MISP Guard: [POST]/events/edit/[UUID]\n    note right of MISP Guard: Outgoing Event is inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [POST]/events/edit/[UUID]\n    MISP A-\u003e\u003eMISP Guard: [POST]/events/edit/[UUID]\n    MISP Guard-\u003e\u003eMISP B: [POST]/events/edit/[UUID]\n    end\n    end \n\n    rect rgb(191, 223, 255)\n    note right of MISP A: PUSH GalaxyClusters\n    MISP B-\u003e\u003e+MISP Guard: [POST]/galaxies/pushCluster\n    note right of MISP Guard: Outgoing Galaxy Cluster is inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [POST]/galaxies/pushCluster\n    MISP A-\u003e\u003eMISP Guard: [POST]/galaxies/pushCluster\n    MISP Guard-\u003e\u003eMISP B: [POST]/galaxies/pushCluster\n    end\n\n    rect rgb(191, 223, 255)\n    note right of MISP A: PUSH Sightings\n    MISP B-\u003e\u003e+MISP Guard: [POST]/sightings/bulkSaveSightings/[UUID]\n    note right of MISP Guard: Outgoing Sightings are inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [POST]/sightings/bulkSaveSightings/[UUID]\n    MISP A-\u003e\u003eMISP Guard: [POST]/sightings/bulkSaveSightings/[UUID]\n    MISP Guard-\u003e\u003eMISP B: [POST]/sightings/bulkSaveSightings/[UUID]\n    end\n    \n    rect rgb(191, 223, 255)\n    note right of MISP A: PUSH AnalystData\n    MISP B-\u003e\u003e+MISP Guard: [POST]/analyst_data/filterAnalystDataForPush\n    MISP A-\u003e\u003eMISP Guard: [POST]/analyst_data/filterAnalystDataForPush\n    MISP Guard-\u003e\u003eMISP B: [POST]/analyst_data/filterAnalystDataForPush\n\n    MISP B-\u003e\u003e+MISP Guard: [POST]/analyst_data/pushAnalystData\n    note right of MISP Guard: Outgoing Analyst Data is inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [POST]/analyst_data/pushAnalystData\n    MISP A-\u003e\u003eMISP Guard: [POST]/analyst_data/pushAnalystData\n    MISP Guard-\u003e\u003eMISP B: [POST]/analyst_data/pushAnalystData\n    end\n```\n\n## PULL\n```mermaid\nsequenceDiagram\n    participant MISP A\n    participant MISP Guard\n    participant MISP B\n\n    rect rgb(191, 223, 255)\n    note right of MISP A: PULL Events \n    MISP A-\u003e\u003eMISP Guard: [GET]/servers/getVersion\n    MISP Guard-\u003e\u003eMISP B: [GET]/servers/getVersion\n    MISP B-\u003e\u003eMISP Guard: [GET]/servers/getVersion\n    MISP Guard-\u003e\u003eMISP A: [GET]/servers/getVersion\n\n    MISP A-\u003e\u003e+MISP Guard: [POST]/events/index\n    note right of MISP Guard: Only `minimal` search requests to /events/index are allowed\n    MISP Guard-\u003e\u003e-MISP B: [POST]/events/index\n    MISP B-\u003e\u003eMISP Guard: [POST]/events/index\n    MISP Guard-\u003e\u003eMISP A: [POST]/events/index\n\n    MISP A-\u003e\u003eMISP Guard: [GET]/events/view/[UUID]\n    MISP Guard-\u003e\u003eMISP B: [GET]/events/view/[UUID]\n    MISP B-\u003e\u003e+MISP Guard: [GET]/events/view/[UUID]\n    note right of MISP Guard: Incoming Event is inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [GET]/events/view/[UUID]\n\n    MISP A-\u003e\u003eMISP Guard: [GET]/users/view/me.json\n    MISP Guard-\u003e\u003eMISP B: [GET]/users/view/me.json\n    MISP B-\u003e\u003eMISP Guard: [GET]/users/view/me.json\n    MISP Guard-\u003e\u003eMISP A: [GET]/users/view/me.json\n    end\n\n    rect rgb(191, 223, 255)\n    note right of MISP A: PULL ShadowAttributes \n    MISP A-\u003e\u003eMISP Guard: [GET]/shadow_attributes/index\n    MISP Guard-\u003e\u003eMISP B: [GET]/shadow_attributes/index\n    MISP B-\u003e\u003e+MISP Guard: [GET]/shadow_attributes/index\n    note right of MISP Guard: Incoming Shadow Attributes are inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [GET]/shadow_attributes/index\n    end\n\n    rect rgb(191, 223, 255)\n    note right of MISP A: GalaxyClusters \n    MISP A-\u003e\u003e+MISP Guard: [POST]/galaxy_clusters/restSearch\n    note right of MISP Guard: Only `minimal` search requests to /galaxy_clusters/restSearch are allowed\n    MISP Guard-\u003e\u003e-MISP B: [POST]/galaxy_clusters/restSearch\n    MISP B-\u003e\u003eMISP Guard: [POST]/galaxy_clusters/restSearch\n    MISP Guard-\u003e\u003eMISP A: [POST]/galaxy_clusters/restSearch\n\n    MISP A-\u003e\u003eMISP Guard: [GET]/galaxy_clusters/view/[UUID]\n    MISP Guard-\u003e\u003eMISP B: [GET]/galaxy_clusters/view/[UUID]\n    MISP B-\u003e\u003e+MISP Guard: [GET]/galaxy_clusters/view/[UUID]\n    note right of MISP Guard: Incoming Galaxy Cluster is inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [GET]/galaxy_clusters/view/[UUID]\n\n    MISP A-\u003e\u003eMISP Guard: [GET]/users/view/me.json\n    MISP Guard-\u003e\u003eMISP B: [GET]/users/view/me.json\n    MISP B-\u003e\u003eMISP Guard: [GET]/users/view/me.json\n    MISP Guard-\u003e\u003eMISP A: [GET]/users/view/me.json\n    end\n\n    rect rgb(191, 223, 255)\n    note right of MISP A: PULL Sightings \n    MISP A-\u003e\u003eMISP Guard: [POST]/sightings/restSearch/event\n    MISP Guard-\u003e\u003eMISP B: [POST]/sightings/restSearch/event\n    MISP B-\u003e\u003e+MISP Guard: [POST]/sightings/restSearch/event\n    note right of MISP Guard: Incoming Sightings are inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [POST]/sightings/restSearch/event\n    end\n    \n    rect rgb(191, 223, 255)\n    note right of MISP A: PULL AnalystData \n    MISP A-\u003e\u003eMISP Guard: [POST]/analyst_data/indexMinimal\n    MISP Guard-\u003e\u003eMISP B: [POST]/analyst_data/indexMinimal\n    MISP B-\u003e\u003e+MISP Guard: [POST]/analyst_data/indexMinimal\n    MISP Guard-\u003e\u003e-MISP A: [POST]/analyst_data/indexMinimal\n\n    MISP A-\u003e\u003eMISP Guard: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json\n    MISP Guard-\u003e\u003eMISP B: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json\n    MISP B-\u003e\u003e+MISP Guard: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json\n    note right of MISP Guard: Incoming Analyst Data is inspected and rejected with 403 if any block rule matches\n    MISP Guard-\u003e\u003e-MISP A: [GET]/analyst_data/index/[Note|Opinion|Relationship]/uuid:[UUID].json\n\n    MISP A-\u003e\u003eMISP Guard: [GET]/users/view/me.json\n    MISP Guard-\u003e\u003eMISP B: [GET]/users/view/me.json\n    MISP B-\u003e\u003eMISP Guard: [GET]/users/view/me.json\n    MISP Guard-\u003e\u003eMISP A: [GET]/users/view/me.json\n    end\n```\n\n\n\n\n\u003e **NOTE: The `MISP A` server needs to have the `misp-guard` hostname configured as the server hostname you are going to pull from, **not** the `MISP B` hostname.**\n\n\n\n## Instructions\n\n### Requirements\n* Python 3.12 or newer.\n* `venv` (recommended).\n\n### Installation\n```bash\n$ git clone https://github.com/MISP/misp-guard.git\n$ cd src/\n$ apt install python3.12-venv\n$ python3.12 -m venv .venv\n$ source .venv/bin/activate\n$ pip3 install -r requirements.txt\n```\n\n### Setup\n\n1. Define your block rules in the `config.json` file.\n2. Start mitmproxy with the `mispguard` addon:\n    ```\n    $ mitmdump -s mispguard.py -p 8888 --certs *=cert.pem --set config=config.json\n    Loading script mispguard.py\n    MispGuard initialized\n    Proxy server listening at *:8888\n    ``` \n    _Add `-k` to accept self-signed certificates._\n\n3. Configure the proxy in your MISP instance, set the following MISP  `Proxy.host` and `Proxy.port` settings accordingly.\n\nDone, outgoing MISP sync requests will be inspected and dropped according to the specified block rules.\n\n\n\u003e NOTE: add `-v` to `mitmdump` to increase verbosity and display debug logs.\n\n### Testing\n ```\n $ pip install pytest pytest-asyncio\n $ src src/\n $ pytest\n ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmisp%2Fmisp-guard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmisp%2Fmisp-guard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmisp%2Fmisp-guard/lists"}